TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)

文章目录

泛型1

泛型2

声明合并

命名空间

 模块1

模块2

声明文件简介


泛型1

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第1张图片

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性 

首先,我们来实现一个函数 createArray

function createArray(length: number, value: any): Array {
  let result = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
 }
  return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']

这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型
Array 允许数组的每一项都为任意类型。但是我们预期的是,数组中每一项都应该是输入的 value 的类型
这时候,泛型就派上用场了

function createArray(length: number, value: T): Array {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
 }
  return result;
}
createArray(3, 'x'); // ['x', 'x','x']

泛型2

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第2张图片

 多个类型参数

function swap(v1:T,v2:U) {
  console.log(v1,v2)
}
swap(10,20);

泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法

function loggingLength(arg: T){
  // Property 'length' does not exist on type 'T'
  console.log(arg.length);
}

这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束

interface Length {
  length: number;
}
function loggingIdentity (arg: T){
  console.log(arg.length);
}
loggingIdentity("Hello")

声明合并

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第3张图片

如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型 

函数的合并

我们可以使用重载定义多个函数类型

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
 } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
 }
}

接口的合并

接口中的属性在合并时会简单的合并到一个接口中

interface Alarm {
  price: number;
}
interface Alarm {
  weight: number;
}

相当于:

interface Alarm {
  price: number;
  weight: number;
}

注意,合并的属性的类型必须是唯一的:

interface Alarm {
  price: number;
}
interface Alarm {
  price: number;  // 虽然重复了,但是类型都是 `number`,所以不会报错
  weight: number;
}

interface Alarm {
  price: number;
}
interface Alarm {
  price: string;  // 类型不一致,会报错
  weight: number;
}

命名空间

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第4张图片

 在真实的应用场景中,当在一个文件中代码量过多,不容易阅读和维护的时候,我们可以通过命名空间的方式将一个文件分离为多个文件
我们来观察下面这个例子:

interface Animal{
  name:string
}
class Cat implements Animal{
  name: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
class Dog implements Animal{
  name: string
  constructor(name:string){
    this.name = name
 }
  sayHello(){
    console.log(this.name)
 }
}
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护

// Animal.ts
namespace AnimalInfo{
  export interface Animal{
    name:string
 }
}
// Cat.ts
namespace AnimalInfo{
  export class Cat implements Animal{
    name: string
    constructor(name:string){
      this.name = name;
   }
    sayHi(){
      console.log(this.name)
   }
 }
}
// Dog.ts
namespace AnimalInfo{
  export class Dog implements Animal{
    name: string
    constructor(name:string){
      this.name = name
   }
    sayHello(){
      console.log(this.name)
   }
 }
}
// index.ts
const c = new AnimalInfo.Cat("猫")
c.sayHi()
const d = new AnimalInfo.Dog("狗")
d.sayHello()

多文件编译

当涉及到多文件时,我们必须确保所有编译后的代码都被加载了。
我们有两种方式

方式一

把所有的输入文件编译为一个输出文件,需要使用 --outFile 标记

tsc --outFile demo.js .\Animal.ts .\Cat.ts .\Dog.ts .\index.ts

方式二

我们可以编译每一个文件(默认方式),那么每个源文件都会对应生成一个 JavaScript 文件。 然后,在页面上通过

 模块1

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第5张图片

从 ECMAScript 2015 开始,JavaScript 引入了模块的概念。TypeScript 也沿用这个概念
模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用 export 形式之一导出它们。 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用 import 形式之一 

interface Animal{ 
  name:string
}
class Cat implements Animal{
  name: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
class Dog implements Animal{
  name: string
  constructor(name:string){
    this.name = name
 }
  sayHello(){
    console.log(this.name)
 }
}
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

 我们用模块化的形式实现

// Animal.ts
export interface Animal{
  name:string
}
// Cat.ts
import { Animal } from "./Animal"
export class Cat implements Animal{
  name: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
// Dog.ts
import { Animal } from "./Animal"
export class Dog implements Animal{
  name: string
  constructor(name:string){
    this.name = name
 }
  sayHello(){
    console.log(this.name)
 }
}
// index.ts
import { Cat } from "./Cat"
import { Dog } from "./Dog"
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

模块2

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第6张图片

模块化的优势不言而喻,换句话说,如果一个语言无法支持模块化,那么他就无法做大型应用程序的开发
接下来我们在来了解一些模块的其他知识 

 别名

当导入的名字特别长,或者不容易写的时候,可以使用别名

import { Animal as AL } from "./Animal"
export class Cat implements AL{
  name: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}

 默认导出

每个模块都可以有一个 default 导出。 默认导出使用 default 关键字标记;并且一个模块只能够有一个 default 导出

export default interface Animal{
  name:string
}
import Animal from "./Animal"
export class Cat implements Animal{
  name: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}

导入整个模块

当导出的对象特别多,需要导入的也很多,这个时候,可以使用导入整个模块的方式 

export interface Animal{
  name:string
}
export interface AnimalInfo{
  age:number
}

import * as AN from "./Animal"
export class Cat implements AN.Animal,AN.AnimalInfo{
  name: string
  age:number
  constructor(name:string,age:number){
    this.name = name;
    this.age = age
 }
  sayHi(){
    console.log(this.name,this.age)
 }
}

声明文件简介

TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)_第7张图片

 typescript中以 .d.ts 为后缀的文件被称为声明文件当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能

声明文件分为三种类型
1、typescript内置声明文件
2、第三方声明文件
3、自定义声明文件

什么是声明语句 

假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过

你可能感兴趣的:(java,TypeScript,html5,前端)