关于typescript:TypeScript基础之联合类型交叉类型类型别名

90次阅读

共计 4227 个字符,预计需要花费 11 分钟才能阅读完成。

联结类型

联结类型示意取值能够为多种类型中的一种,应用 | 宰割每个类型。

let a: number | string | boolean;
a = 100;
a = 'xman';
a = true;

函数中应用:

const test = (info: string | number) => {// ...}

束缚取值

const num: 1 | 2 = 1;
type isMan = true | false;
type EventNames = 'click' | 'scroll' | 'mousemove';

以上 1 | 2, true | false, ‘click’ | ‘scroll’ | ‘mousemove’ 被称为字面量类型,别离为数字、布尔、字符串字面量类型,能够用来束缚取值只能是其中几个值中的一个。

穿插类型

穿插类型是将多个类型合并为一个类型,应用 & 定义穿插类型。

能够将多个接口类型合并成一个类型,实现等同于接口继承的成果

interface A {
  name: string;
  age: number;
}

interface B {
  name: string;
  height: string;
}

type Person =  A & B;  // 相当于求并集
let person: Person = {name: 'xman', age: 18, height: '60kg'};

留神:

  1. 原子类型能够合并吗?
    如果仅仅把根本类型、字面量类型、函数类型等原子类型合并成穿插类型,是没有任何用途的。因为任何类型都不能满足同时属于多种原子类型。

    type Useless = string & number;  // 就是个 never
  2. 合并的接口类型存在同名属性是什么成果?
    如果同名属性的类型兼容,比方一个是 number,另一个是 number 的子类型、数字字面量类型,合并后属性的类型就是两者中的子类型。

    interface A {
      name: string;
      age: number;
      id: number;
    }
    
    interface B {
      name: string;
      height: string;
      id: string;
    }
    
    type Person =  A & B;  
    let person: Person = {name: 'xman', age: 18, height: '60kg', id: 1};
    // Type 'number' is not assignable to type 'number & string'.  
    // Type 'number' is not assignable to type 'string'.

    以上代码提醒 name 属性值呈现类型谬误。

    interface A {
      name: string;
      age: number;
      id: number;
    }
    
    
    interface B {
      name: string;
      height: string;
      id: 1;  // 数字字面量类型为 1
    }
    
    type Person =  A & B;  
    let person: Person = {name: 'xman', age: 18, height: '60kg', id: 1};

    以上代码中 interface B 的 name 属性的类型就是数字字面量类型 1,因而咱们不能把任何非 1 之外的值赋值为 id 属性;
    上面看下同名属性非根本数据类型的合并状况:

    interface A {
      info: {name: string}
    }
    
    interface B {
      info: {age: number}
    }
    
    interface C {
      info: {bool: boolean}
    }
    
    type ABC = A & B & C;
    let abc: ABC = {
      info: {
     name: 'xman',
     age: 18,
     bool: true
      }
    }

    编译胜利,后果如下:

    var abc = {
     info: {
         name: 'xman',
         age: 18,
         bool: true
     }
    };

    类型别名

    type: 其作用就是给类型起一个新名字,能够作用于原始值(根本类型)、联结类型、元祖以及其余任何你须要手写的类型。
    例子:

    // 根本类型
    type Num = Number;
    let n: Num = 1;
    
    // 联结类型
    type Shape = {kind: "circle"; radius: number} | {kind: "square"; x: number} | {kind: "triangle"; x: number; y: number};
    
    function area(s: Shape) {if (s.kind === "circle") {return Math.PI * s.radius * s.radius;} else if (s.kind === "square") {return s.x * s.x;} else {return (s.x * s.y) / 2;
      }
    }
      
    // 对象
    type UserInfo = {name: string};
    
    // 函数
    type GetInfo = () => string;
    
    // 元祖 
    type Size = [number, number];
    let x: Size = [10, 99.9]; 
    ````
    ` 留神:` 
    起别名不会新建一个类型 - 它创立了一个新 名字来援用那个类型。给根本类型起别名通常没什么用。# type 与 interface 区别 
    ### 1. 都能够形容一个对象或者函数 
    
    interface  

    interface IPerson {
    name: string;
    age: number;
    }

interface SetPerson {
(name: string, age: number):void;
}


type  

type Person = {
name: string;
age: number;
}

type SetPerson = (name: string, age: number) => void;

` 注:` 在 ts 编译成 js 后,所有的接口和 type 都会被擦除掉  
### 2. 拓展

接口能够扩大,但 type 不能 extends 和 implement, 然而 type 能够通过穿插类型实现 interface 的 extends 行为。interface 能够 extends type,同时 type 也能够与 interface 类型穿插

1. interface extends interface, type 穿插类型能够实现

interface IAnimal {
name: string;
}

interface IPerson extends IAnimal{
age: number;
}

// type 穿插类型能够实现
type Animal = {
name: string;
}

type Person = Animal & {age: number};

  

2. interface extends type, type 与 interface 穿插  

type Animal = {
name: string;
}

interface IPerson extends Animal {
age: number;
}

// type 与 interface 穿插
interface IAnimal {
name: string
}
type Person = IAnimal & {
age: number;
}

### 3. Implements 
类能够以雷同的形式实现接口或类型别名。然而请留神,类和接口被认为是动态的。因而,它们不能实现 / 扩大命名联结类型的类型别名  

interface Point {
x: number;
y: number;
}

class SomePoint implements Point {
x: 1;
y: 2;
}

type Point2 = {
x: number;
y: number;
};

class SomePoint2 implements Point2 {
x: 1;
y: 2;
}

type PartialPoint = {x: number;} | {y: number;};

// A class may only implement another class or interface.
class SomePartialPoint implements PartialPoint {
x: 1;
y: 2;
}

### 4. extends class
类定义会创立两个货色:类的实例类型和一个构造函数。因为类能够创立出类型,所以你可能在容许应用接口的中央应用类。

class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}

### 5. type 能够申明根本类型别名、联结类型、元祖等类型

type Num = Number;

// 联结类型
type Shape = {kind: “circle”; radius: number} | {kind: “square”; x: number} | {kind: “triangle”; x: number; y: number};

// 元祖
type Size = [number, number];

type 还能够应用 typeof 获取实例的类型进行赋值  

let div = document.createElement(‘div’);
type B = typeof div;

### 6. 申明合并 
接口能够定义屡次,并将被视为单个接口(即所有申明属性的合并),而 type 不能定义屡次  

interface IPerson {
name: string;
age: number;
}
interface IPerson {
height: string;
}
let person:IPerson = {
name: ‘xman’,
age: 18,
height: ’60kg’
}


### 7. 映射类型 
type 能应用 in 关键字生成映射类型,但 interface 不行  
语法与索引签名的语法类型,外部应用了 for .. in。具备三个局部:-   类型变量 K,它会顺次绑定到每个属性。-   字符串字面量联结的 Keys,它蕴含了要迭代的属性名的汇合。-   属性的后果类型。

type Keys = ‘name’ | ‘height’;

type Person = {

}

let person: Person = {
name: ‘xman’,
height: ’60kg’
}

### 其余 

export default interface IPerson {
name: string;
age: number;
}

type Person = {
name: string;
}
export default Person;


# 参考资料 
[https://www.tslang.cn/docs/handbook/declaration-merging.html](https://www.tslang.cn/docs/handbook/declaration-merging.html)   
[Interfaces vs Types in TypeScript - Stack Overflow](https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript) 

正文完
 0