假如咱们要实现一个函数,这个函数会返回任何传入它的值。不用泛型的话就只能使用any或者是用类型推断。这时用泛型就是一个很好的选择。ide
function identity<T>(arg: T): T {
return arg;
}
复制代码
泛型简单来讲就是当你传进来的参数是string,那么T在这个执行中就等于string。函数
官方文档所说ui
never 类型表示的是那些永不存在的值的类型。 例如, never 类型是那些老是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也多是 never 类型,当它们被永不为真的类型保护所约束时。 never 类型是任何类型的子类型,也能够赋值给任何类型;然而,没有类型是 never 的子类型或能够赋值给 never 类型(除了 never 自己以外)。 即便 any 也不能够赋值给 never。spa
never不能被赋值,并且表明的是没法到达的终点。也就是说你的程序就不该该执行到这,never的其中一个用法就是收窄类型。code
下面举个尤大大说的例子,假如你有一个联合类型文档
interface Foo {
type: 'foo'
}
interface Bar {
type: 'bar'
}
type All = Foo | Bar
复制代码
在 switch 当中判断 type,TS 是能够收窄类型的 (discriminated union):源码
function handleValue(val: All) {
switch (val.type) {
case 'foo':
// 这里 val 被收窄为 Foo
break
case 'bar':
// val 在这里是 Bar
break
default:
// val 在这里是 never
const exhaustiveCheck: never = val
break
}
}
复制代码
注意在 default 里面咱们把被收窄为 never 的 val 赋值给一个显式声明为 never 的变量。若是一切逻辑正确,那么这里应该可以编译经过。可是假如后来有一天你的同事改了 All 的类型:string
type All = Foo | Bar | Baz
复制代码
然而他忘记了在 handleValue 里面加上针对 Baz 的处理逻辑,这个时候在 default branch 里面 val 会被收窄为 Baz,致使没法赋值给 never,产生一个编译错误。因此经过这个办法,你能够确保 handleValue 老是穷尽 (exhaust) 了全部 All 的可能类型。it
keyof的做用就是取全部的键,只取键,而且keyof 取到键后会保存为联合类型。io
interface person {
sex: string;
age: number;
}
type keys = keyof person; // type keys =sex | age
复制代码
in的做用是遍历全部的健
type age = 'dog' | 'cat';
type age={
[key in age]:number;
};
/* 至关于
* type age={
* dog:number;
* cat:number;
*/ };
复制代码
Partial,Required,Readonly这三个比较简单,因此就一块儿讲了
Partial做用是将属性变为可选属性
type Partial<T> = {
[P in keyof T]?: T[P];
};
复制代码
用法:
interface Age:{
son:number;
father:number;
};
type person=Partial<Age>
/* person就等于
*interface person:{
* son?:number;
* father?:number;
*/};
复制代码
下面同理
2. Required做用是将属性变成必须属性
type Required<T> = {
[P in keyof T]-?: T[P];
};
复制代码
Readonly做用是将属性变成只读属性
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
复制代码
pick是筛选出我想要的属性。
源码以下:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
复制代码
interface Age:{
son:number;
father:number;
};
type person=Pick<Age,'son'>
/* person就等于
*interface person:{
* son:number;
*/};
复制代码
pick会在Age中筛选出son的属性赋值给person
Record将某个类型转化成目标类型。
官方源码:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
复制代码
将K中的每一个属性([P in K]),都转为T类型
interface Age:{
son:number;
father:number;
};
type person=Record<Age,string>
/*
*这时person就等于:
*interface person:{
* son:string;
* father:string;
* };
*/复制代码