首先,我有一个类型定义,可以使用keyof
type Numeric<T> = {
[K in keyof T]: number
}
下面是我要使用的课程。
class Entity {
aNumber: number;
}
下面是一个接受通用类型参数和类型为Numberic<T>
的局部变量的函数。但是当我分配{ aNumber: 1 }
时,出现了编译错误。
const fn = <T extends Entity>() => {
const n: Numeric<T> = {
// ^
// Type '{ aNumber: number; }' is not
// assignable to type 'Numeric<T>'
aNumber: 1
};
};
我不知道为什么无法将{ aNumber: number; }
分配给Numeric<T>
,因为类型实参T
必须从Entity
扩展并且它必须包含一个名为{{ 1}}。这意味着aNumber
必须是T类型的密钥,并且应该能够分配给aNumber
。
答案 0 :(得分:3)
该错误消息具有误导性。但是,有一个错误,这就是TypeScript正在捕获的错误。确实,Entity
没什么问题:
type Numeric<T> = {
[K in keyof T]: number
}
interface Entity {
aNumber: number
}
// No error
const n: Numeric<Entity> = {
aNumber: 1
};
但是,当您说T extends Entity
时,它会打开非数字值,例如
type Numeric<T> = {
[K in keyof T]: number
}
interface Entity {
aNumber: number
}
// No error
const n: Numeric<Entity> = {
aNumber: 1
};
interface X extends Entity {
notANumber: string
}
// Error. Thank you TypeScript
const o: Numeric<X> = {
aNumber: 1
};
在T extends Entity
中使用Numeric
时发生错误。
答案 1 :(得分:1)
<T extends Entity>
施加的约束应被视为T
应该满足的最低要求。这表示“ T
至少应包含aNumber: number
对”。
让我们看看const n: T
。这意味着“ n至少应包含T
中的任何键值对”。
现在我们知道,T
有一对aNumber: number
,但请记住,这只是最低要求。 T
也可能是{ aNumber: number; aString: string }
。因此,这也会给您带来错误。
// if you understand this:
const n: { aNumber: number; aString: string } = { aNumber: 42 } // error, of course
// you see why this is an error:
const n: T = { aNumber: 42 } // also error
您永远无法说出T
的确切含义。 keyof T
很好,我们肯定至少知道T
的钥匙之一。
const k: keyof T = "aNumber"
为证明我的观点,让我们回顾一个非通用案例。以@basarat的代码为例,这里的X
不是流派的。
type Numeric<T> = {
[K in keyof T]: number
}
type OptionalNumeric<T> = {
[K in keyof T]?: number
}
interface Entity {
aNumber: number
}
interface X extends Entity {
notANumber: string
}
// Error, because `notANumber` is missing
const o: Numeric<X> = { aNumber: 1 };
// Correct
const o1: Numeric<X> = { aNumber: 1, notANumber: 2 };
// Also correct, because all keys are optional.
const o2: OptionalNumeric<X> = { aNumber: 1 };
旁注。以上应解释您的情况。但是,我确实相信TS中存在错误。
我认为,如果您在原始情况下使用OptionalNumeric
,那么您想要的应该可以工作。但是事实并非如此。涉及泛型类型参数时应该是一个缺陷。