我有这样的代码,可以从接口中排除属性
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
interface MyType {
id: string
timeout: number
delta: number
}
let value: Omit<MyType, 'id'> = {
timeout: 10,
delta: 5,
}
这还可以,但我不能将属性从泛型类型中排除,比如:
function foo<T>(x: T) {
let value: Omit<T, 'id'> = {
timeout: 10,
delta: 5,
}
}
foo<MyType>({ timeout: 10, delta: 5 })
现在我收到错误消息Type '"id"' does not satisfy the constraint 'keyof T'
我做错了什么?
这是因为编译器不能仅根据函数声明来检查类型T
是否实际具有属性id
。我们可以添加一个约束来告诉编译器将要传递的内容将具有id
属性:
function foo<T extends { id: string }>(x: Omit<T, 'id'>) {
let value: Omit<T, 'id'> = x;
}
foo<MyType>({ timeout: 10, delta: 5 })
您会注意到,我没有用对象文字初始化函数内的value
变量,这是因为如果您不知道完整类型,就无法创建对象文字。关于T
,我们只知道它具有和id
属性,对于T
具有的其他属性,它们具有什么类型以及是否需要它们,我们一无所知。
如果你真的需要在函数中初始化一个泛型类型的变量,唯一(unsafe(的方法是使用类型断言:
function foo<T extends MyType>(x: Omit<T, 'id'>) {
let value = {
timeout: 10,
delta: 5,
} as unknown as Omit<T, 'id'> // replace unknown with any for ts before 3.0
}