我希望修复addRandomValue
函数的类型,以便Typescript编译器不允许下面的调用,因为baz
不在FooBar
中。
type WithRandomNumber<T> = T & { randomValue: number; };
function addRandomValue<T>(inputObj: T): WithRandomNumber<T> {
return {
...inputObj,
randomValue: Math.random(),
};
}
interface FooBar {
foo: string;
bar: number;
};
const resultObj: WithRandomNumber<FooBar> = addRandomValue({
foo: 'hello',
bar: 100,
baz: true,
});
也就是说,我想约束addRandomValue
的通用T
(因此inputObj
的类型),因此,如果预期的返回类型是WithRandomNumber<Foobar>
(因为这是我们分配返回值的变量类型),那么T
必须等于FooBar
。
您不能强迫编译器阻止基于LH类型声明的赋值,而是必须在调用函数时传递泛型参数:
type WithRandomNumber<T> = T & { randomValue: number; };
function addRandomValue<T>(inputObj: T): WithRandomNumber<T> {
return {
...inputObj,
randomValue: Math.random(),
};
}
interface FooBar {
foo: string;
bar: number;
};
const resultObj = addRandomValue<FooBar>({
foo: 'hello',
bar: 100,
baz: true,
});
问题不在于编译器不够聪明,它与Javascript如何根据规范进行评估有关。由于您没有在调用站点传递泛型参数,因此它推断类型{foo: string bar: number, baz: boolean }
并评估RH表达式然后它将结果分配给具有您声明的类型的LH变量。因为TS是结构类型的,这确实是一个有效的赋值,因为它具有FooBar所需的所有属性:
const foo = {
foo: 'hello',
bar: 100,
baz: true,
};
const bar: FooBar = foo;
游乐场