本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士
泛型
类型参数化
即便是类型也可以更灵活,使函数更具有通用性,这是由于js本身过于灵活的特性决定的。
function fn<T>(arg: T){
return arg
}
传入的类型是什么类型,函数fn
接收的参数就是什么类型。这可和any
不一样,因为any
会丢失类型,而泛型是根据传入的参数决定类型,是参数类型的动态化,在调用时决定。
调用时可以不指定函数,ts会自动进行类型推导,而且推导出来的类型会更具体。但这样会增加一些ts编译器的负担,并且推导出来的类型并不总是正确的。
const fn1 = fn<number>(18)
const fn2 = fn('flten')
泛型接口和泛型类
泛型接口,默认指定为string
interface Animal<T = string> {
name: T,
age: number,
food:T,
}
动态决定泛型参数类型
const monkey:Animal<string> = {
name: 'flten',
age 18,
food: 'noodle',
}
泛型类
class Animal<T = string> {
name: T,
food: T,
constructor(name:T, food:T){
this.name = name
this.food = food
}
}
const bird = new Animal('flten', 'pest')
泛型约束
对传入的参数类型结构进行约束,规定必须包含特定属性。
interface hasLength {
length:number
}
function getLength<T extends hasLength>(arg:<T>):<T>{
return arg
}
这样就可以记录参数属性的类型。
还可以避免调用时出错,进行强制约束:
function getAnimalProperty<O, K extends keyof O>(obj: O, key: K){
return obj[key]
}
const bird = {
name:'bird',
food:'pest',
}
const birdFood = getAnimalProperty(bird, 'food')
这样就能保证传入的属性一定是存在于对象上的。
内置工具与实现
Partial将类型的属性都变为可选
interface Info {
name : string,
age : number,
}
type optionalInfo = Partial<Info>
得到的新类型为:
type optionalInfo = {
name?: string | undefined;
age?: number | undefined;
}
实现Partial:使用映射进行属性遍历
type newPartial<T> = {
[key in keyof T]?: T[key]
}
Rquired将属性的选项都变为必选
interface Info {
name? : string,
age? : number,
}
type optionalInfo = Required<Info>
得到新的类型:
type optionalInfo = {
name: string;
age: number;
}
自己实现 Required,也是使用映射进行属性遍历
type newRequired<T> = {
[key in keyof T]-?: T[key]
}
Readonly将类型所有属性都变为readonly只读
interface Info {
name? : string,
age? : number,
}
type optionalInfo = Readonly<Info>
得到新的类型:
type optionalInfo = {
readonly name?: string | undefined;
readonly age?: number | undefined;
}
自己实现 Readonly:
type newReadonly<T> = {
readonly [key in keyof T]: T[key]
}
Record<Keys, Types>
构造对象类型,规定属性和值的类型
interface Info {
name? : string,
age? : number,
}
type k = "a" | "b" | "c"
type optionalInfo = Record<k, Info>
得到的新类型为:
type optionalInfo = {
a: Info;
b: Info;
c: Info;
}
自己实现 Record
type newRecord<K extends keyof Info, V> = {
[key in K]: V
}
Pick<Type, Types>
构造一个类型,并从给定的类型中选出需要的属性
interface Info {
name? : string,
age? : number,
}
type optionalInfo = Pick<Info, "name">
得到新的类型为
type optionalInfo = {
name?: string | undefined;
}
自己实现 Pick
type newPick<T, K extends keyof T> = {
[p in K]: T[p]
}
Omit<Type, Keys>
构造类型,将给定类型中的指定属性进行过滤
interface Info {
name? : string,
age? : number,
}
type optionalInfo = Omit<Info, "name">
得到的新类型为:
type optionalInfo = {
age?: number | undefined;
}
自己实现 Omit
type newOmit<T, K extends keyof T> = {
[p in keyof T as p extends K ? never : p]: T[p]
}
Exclude<UnionType, ExcludedMembers>
将联合类型中的指定类型排除
type k = "a" | "b" | "c"
type optionalInfo = Exclude<k, "a">
得到的新类型为:
type optionalInfo = "b" | "c"
自己实现 Exclude
type newExclude<T, E> = T extends E ? never : T
Extract<UnionType, ExtractMembers>
将联合类型中的指定类型保留
type k = "a" | "b" | "c"
type optionalInfo = Extract<k, "a">
得到的新类型为:
type optionalInfo = "a"
自己实现 Extract:
type newExtract<T, E> = T extends E ? T : never
NoneNullable<Type>
构造类型,从中排除掉null
,undefined
类型
type k = "a" | "b" | "c" | null | undefined
type optionalInfo = NonNullable<k>
得到的新类型为:
type optionalInfo = "a" | "b" | "c"
自己实现 NoneNullable:
type newNoneNullable<T> = T extends null | undefined ? never : T
ReturnType<Type>
构造一个含有Type
函数返回值的类型
下面会取到函数的返回值类型:
function fn():string{
return 'a'
}
type callbackType = ReturnType<typeof fn>
得到的新类型为:
type callbackType = string
自己实现 ReturnType:
type newReturnType<T extends (...args:any[])=>any> = T extends (...args:any[])=> infer R ? R : never
InstanceType<Type>
取到构造函数的类型
class Animal {}
function factory<T extends new (...args: any[]) => any>(constructor:T):InstanceType<T>{
return new constructor()
}
const d1 = factory(Animal)
这样就能保证d1
类型的正确
const d1: Animal
自己实现 InstanceType:
type newInstanceType<T extends new (...args:any[])=>any> = T extends new (...args:any[])=> infer R ? R : never
本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士