由实际使用例子展开:
- 获取对象中属性的值的方法
function getProp(obj, attr) {
return obj[attr]
}
let obj = { name: "jack", age: 10 }
getProp(obj, 'age')
添加完整类型约束如下:
interface IUser {
name: string,
age: number,
}
function getProp<T extends keyof IUser>(obj: IUser, attr: T):IUser[T] {
return obj[attr]
}
let obj: IUser = { name: "jack", age: 10 }
getProp(obj, "age")
其中使用到了 interface,泛型,extends,keyof 的使用,其中 keyof 作用于 interface 或者 type,对比的 typeof 则是作用于 obj,使用比较如下:
// keyof,对类型进行操作,取类或者interface的键组成联合类型
interface IUser { name:string, age:number }
type IUserType = { name:string, age:number }
type UserKeys = keyof IUser // 类似 type UserKeys = 'name' | 'age'
type UserKeys2 = keyof IUserType
let key1:UserKeys = 'name'
let key2:UserKeys2 = 'name'
// typeof,对对象进行操作,生成类似 IUser 的结构
let obj = { name: "jack", age: 18 }
type IUserType2 = typeof obj // 类似于 type IUserType2 = { name:string, age:number }
let obj2: IUserType2 = { name: "bob", age: 20 }
- 通用方法,根据第一个参数,决定其他参数
interface IMessageBoxConfig {
title?: String,
content: String,
}
interface IUserInfo {
/**用户名称 */
name: String,
}
type ModuleFuncsMap = {
loading: (visible: Boolean, timeout?: Number) => Array<any>,
messageBox: (config: IMessageBoxConfig) => Boolean,
getUserInfo: (id: string) => IUserInfo
}
declare function run<
K extends keyof ModuleFuncsMap,
P extends Parameters<ModuleFuncsMap[K]>,
R extends ReturnType<ModuleFuncsMap[K]>
>(
moduleName: K,
...options: P
): R
let b = run("messageBox", { content: "这是必选的内容" })
let c = run("getUserInfo", "123132")
console.log(c.name, "utils.ts::244行");
但上面的写法,提供了一个入口,实时更改泛型,绕过预期的参数和返回值的限制,如
// 如下,就直接可以更改参数和结果了
run<'messageBox', any, true>('messageBox', { aaa: 100 })
解决方式是,尽量少定义泛型参数
type RunOptions<K extends keyof ModuleFuncsMap> = Parameters<ModuleFuncsMap[K]>;
type RunResults<K extends keyof ModuleFuncsMap> = ReturnType<ModuleFuncsMap[K]>;
declare function run<
K extends keyof ModuleFuncsMap
>(
moduleName: K,
...options: RunOptions<K>
): RunResults<K>
待续……