最近在学习ts类型体操,看到一题很有意思: 「重学TS 2.0 」TS 练习题第七题 #25
type EmptyObject = {
[P in PropertyKey]: never
}
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
prop: "TS"
}
type SomeType = {
prop: string
}
type StrictType<T1 extends T2, T2> = {
[P in keyof T1]: P extends keyof T2 ? T1[P] : never
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
declare function takeSomeTypeOnly<T extends SomeType>(x: StrictType<T, SomeType>): T
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
我的疑惑是在这一行
declare function takeSomeTypeOnly<T extends SomeType>(x: StrictType<T, SomeType>): T
请问在不明确传递泛型参数 T 的情况下,typescript 是如何解析 StrictType<T, SomeType> 的?
chatGPT 回答:
在这段代码中,泛型参数 T 的类型是在调用函数 takeSomeTypeOnly 的时候传递的。当调用该函数时,函数的参数类型是 StrictType<T, SomeType>,所以输入类型 T 必须满足扩展自 SomeType 的条件。
因此,当你调用 takeSomeTypeOnly 时,你必须提供一个类型 T,这个类型必须继承自 SomeType,并且这个类型及其所有属性必须符合 StrictType<T, SomeType> 的约束。
例如,假设你有以下代码:
在这种情况下,类型参数 T 的类型是 MyType。因为 MyType 扩展自 SomeType,所以它是合法的。而且,由于 MyType 符合 StrictType<MyType, SomeType> 的约束,所以它也是合法的。因此,在这种情况下,类型参数 T 的类型是 MyType。