typescript重难点知识点讲解

241 阅读4分钟

可索引类型

typescript有两种可索引类型,一种是number类型的索引,一种是字符串类型的索引,number类型的索引可以和字符串类型的索引搭配使用,但是number类型的索引的返回值必须是字符串索引类型的子类型

number类型的索引:使用索引类型的变量可为数组,然后通过索引获取数据

interface App {
    [index:number]:string
}
var var1:App=["1","2"];

console.log(var1[0]);
console.log(var1[1]);
返回结果:

1
2

number类型的索引:使用索引类型的变量可以是对象,对象的键是number类型,也可以为string类型

interface App {
    [index:number]:string
}
var var1:App={11:"返回strin1",22:"返回string2"}

console.log(var1[11]);
console.log(var1[22]);
返回结果:
返回strin1
返回string2

interface App {
    [index:number]:string
}
var var1:App={"11":"返回strin1","22":"返回string2"}

console.log(var1[11]);
console.log(var1[22]);

返回结果:
返回strin1
返回string2

当变量使用number索引类型时,即使是通过number来进行索引,但是实际还是将number类型转化为string,然后通过string类型进行索引。

这就是为什么用一个key为string类型的对象赋值给number索引类型的变量也是可以的。

当number索引类型的返回类型不是string索引类型返回类型的子类的时候,编译不会通过

如下:Animal不满足为·Dog的子类,所以编译器会报错。

class Animal {
    name: string;
}
class Dog extends Animal {
    breed: string;
}
// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
interface NotOkay {
    [x: number]: Animal;
    [x: string]: Dog;
}

interface和type类型的区别

interface和type都可以用来定义Object类型和function类型

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

interface SetPoint{
    (x:number,y:number):void;
}

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

type SetPoint2 = (x:number,y:number) => void;

interface只可以定义class,Object,Function类型,但是type可以定义基本类型和复合类型

type Name = string;

type PartialPointX = {x:number;};
type PartialPointY = {y:number;};

type PartialPoint = PartialPointX | PartialPointY;

type Data = [number,string,boolean];

interface 和type可以碧池继承

interface extends interface
interface extends type
type extends type
type extends interface

类可以implements interface和type类型,但是不能实现/继承 联合类型的type

type不能重复定义,但是interface可以重复定义,并自动进行合并。

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

const point:Pint = {x:1,y:2};

## 泛型

泛型可以应用于function,class,intereface,type,但是不可以用于类的静态成员。

泛型用于function的例子:

function log<T>(value: T): T {
    console.log(value);
    return value;
}

// 两种调用方式
log<string[]>(['a', ',b', 'c'])
log(['a', ',b', 'c'])
log('Nealyang')
  • T, K extends keyof T>约束了这是一个泛型函数

    • keyof T 就是取 T 中的所有的常量 key(这个例子的调用中),即为:"name" | "age"
    • K extends keyof Person 即为 K 是 "name" or "age"
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
}

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

let person: Person = {
    name: 'Jarid',
    age: 35
};
let strings: string[] = pluck(person, ['name', 'name', 'name']); //["Jarid", "Jarid", "Jarid"]
console.log(strings)

partial

Partial的作用就是将传入的属性变为可选。实现:

type Partial<T> = { [P in keyof T]?: T[P] };

Required 的作用是将传入的属性变为必选项, 源码如下

type Required<T> = { [P in keyof T]-?: T[P] };

Readonly

将传入的属性变为只读选项, 源码如下

type Readonly<T> = { readonly [P in keyof T]: T[P] };

Record

该类型可以将 K 中所有的属性的值转化为 T 类型,源码实现如下:

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

Pick

T 中取出 一系列 K 的属性

/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

Exclude

Exclude 将某个类型中属于另一个的类型移除掉。

/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;

Extract

Extract 的作用是提取出 T 包含在 U 中的元素,换种更加贴近语义的说法就是从 T 中提取出 U,源码如下:

/**
 * Extract from T those types that are assignable to U
 */
type Extract<T, U> = T extends U ? T : never;

Omit

PickExclude 进行组合, 实现忽略对象某些属性功能, 源码如下:

/**
 * Construct a type with the properties of T except for those in type K.
 */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

类型断言

有时候编译器并不能识别出变量的类型,这时候我们可以给变量断言为某个类型,这样就可以使用此类型中的相关属性,从而达到欺骗编译器的效果,

但是注意类型断言要根据实际情况,类型断言发生在编译阶段,不恰当的断言可能会在运行期间报错。

推荐类型断言的预发使用 as关键字,而不是<> ,防止歧义