TS面试强化练习

232 阅读2分钟

接口定义练习

/* 自定义学生对象 要求包含可选属性*/
interface Student {
    name: string,
    age: number,
    hobbies?: string[],
}

函数定义练习

/* 
定义一个函数类型 
规定入参必须为string或number 
当入参为number时返回值为string 
当入参为string时返回值为number 
*/
// 方法1:别名定义函数类型
type MyMethod<T extends string | number> = (arg: T) => T extends string ? number : string

// 方法2:使用函数接口定义
interface MyMethod<T extends string | number> {
    (arg: T): T extends string ? number : string
}

const mm1: MyMethod<string> = (arg: string) => {
    return 0
}
const mm2: MyMethod<number> = (arg: number) => {
    return ''
}

泛型工具定义练习1

/* 手动实现Required(将接口的所有字段变必选) */
type MyRequired<T> = {
    [P in keyof T]-?: T[P]
}
type RequiredStudent = Required<Student>
type MyRequiredStudent = MyRequired<Student>
/* 手动实现Partial(将接口的所有字段变可选) */
type MyPartial<T> = {
    [P in keyof T]+?: T[P]
}
type PartialStudent = Partial<Student>
type MyPartialStudent = MyPartial<Student>
/* 手动实现Readonly(将接口的所有字段变只读) */
type MyReadonly<T> = {
    readonly [P in keyof T]: T[P]
}
type RoStudent = Readonly<Student>
type MroStudent = MyReadonly<Student>
/* 手动实现NonNullable(从联合类型中排除null和undefined) */
type MyNonNullable<T> = T & {}
type NnResult = NonNullable<Student | null | number>
type MnnResult = MyNonNullable<Student | null | number>
/* 手动实现ReturnType(提取函数定义中返回值的类型) */
type MyReturnType<F extends (...args: any) => any> = F extends (...args: any) => infer R ? R : void
type Result = ReturnType<MyMethod<string>>
type MyResult = MyReturnType<MyMethod<string>>

泛型工具定义练习2

/* 手动实现Extract(从属性列表中提取特定字段) */
type MyExtract<K0, K1> = K0 extends K1 ? K0 : never
type Extracted = Extract<keyof Student, 'name' | 'gender'>
type MyExtracted = MyExtract<keyof Student, 'name' | 'gender'>
/* 手动实现Exclude(从属性列表中排除特定字段) */
type MyExclude<T, U> = T extends U ? never : T
type Excluded = Exclude<keyof Student, 'name' | 'gender'>
type MyExcluded = MyExclude<keyof Student, 'name' | 'gender'>
/* 手动实现Pick(从接口中选取特定字段) */
type MyPick<T, K extends keyof T> = {
    [P in K]: T[P]
}
type Picked = Pick<Student, 'name' | 'age'>
type MyPicked = MyPick<Student, 'name' | 'age'>
/* 手动实现Omit(从接口中忽略特定字段) */
type MyOmit<T, K extends keyof T> = {
    // 方案1:先使用Exclude过滤好T的属性列表 再逐个读取属性类型
    // [P in Exclude<keyof T, K>]: T[P]

    // 方案2:从T中手动过滤属性列表
    [P in keyof T as P extends K ? never : P]:  T[P]
}
type Omitted = Omit<Student, 'name' | 'age'>
type MyOmitted = MyOmit<Student, 'name' | 'age'>
// 手动实现Record(定义特定键值类型的字典)
type MyRecord<K extends keyof any, T> = {
    [P in K]: T
}
type Recorded = Record<string, any>
type MyRecorded = MyRecord<string, any>