似乎将输入参数推断为泛型索引签名并不能像预期的那样工作(或者我完全遗漏了一些?)。
如何推断返回类型并正确验证输入?
interface Styles {
contentAlign?: string;
zIndex?: number;
}
function createTheme<S extends { [key: string]: Styles }>(theme: S) {
return theme;
}
// this works, foo is marked as invalid
const style: Styles = {
zIndex: 1,
foo: 'bar', // <-- invalid
};
// once I try to use the Styles as index signature it allows other properties
const t = createTheme({
Button: {
zIndex: 1,
foo: 'bar', // <-- valid??
},
});我希望使用Type { foo: "bar" } is not assignable to type Styles,但它似乎是一个有效的输入
发布于 2019-08-12 20:31:55
S extends { [key: string]: Styles }将意味着S可以是{ [key: string]: Styles }的子类型。但这也意味着S的任何属性也可以是Styles的子类型,因此这意味着任何给定键实际上可以具有比Styles中指定的属性更多的属性。
通常,在OOP中,允许在需要基类型的情况下赋值一个子类型,只有当对象字面量直接分配给特定类型时,Typescript才会执行额外的属性检查。在为泛型类型参数赋值时,编译器不会执行过多的属性检查,因为它假定您希望允许子类型(毕竟S extends {...}读取任何扩展{...}的类型S )。
在您的示例中,由于您希望允许任何键,但实际上又不希望禁用对Styles的额外属性检查,因此我将使用对象的键而不是整个对象作为类型参数:
interface Styles {
contentAlign?: string;
zIndex?: number;
}
function createTheme<K extends PropertyKey>(theme: Record<K, Styles>) {
return theme;
}
// this works, foo is marked as invalid
const style: Styles = {
zIndex: 1,
foo: 'bar', // <-- invalid
};
// once I try to use the Styles as index signature it allows other properties
const t = createTheme({
Button: {
zIndex: 1,
foo: 'bar', // <-- error
},
Header: {
zIndex: 1,
foo: 'bar', // <-- error
},
});https://stackoverflow.com/questions/57461081
复制相似问题