所以我试图定义一个可以具有相同类型的嵌套属性的类型/接口。我的代码:
type TMessagesFormat = { [key: string]: string };
interface TMessages {
messages: TMessagesFormat;
}
interface TGroupMessages {
messages?: TMessagesFormat;
controls: { [key: string]: TMessages | TGroupMessages }
}
let groupMessages: TGroupMessages = {
controls: {
username: { messages: {required: 'Username required'} }
}
}
let messages: TGroupMessages = {
controls: {
username: { messages: { required: 'Username required' } },
passwordGroup: {
messages: { nomatch: 'Passwords doesn\'t match' },
controls: {
password: { messages: { required: 'Password required' } }
}
}
}
};
类型检查适用于username和passwordGroup,但是passwordGroup中的控件可以是任何东西,TS编译器也不会抱怨。实际上,如果我在controls: 'whatever'
对象文字中放置username
属性(字符串不应该是有效类型),代码仍会编译而没有任何警告或错误。这可能吗?怎么样?谢谢!
答案 0 :(得分:1)
看起来这是a bug in TypeScript,对于对象文字的过度属性检查似乎不会以你期望的方式发生。最短的再现:
interface A {
a: string;
}
interface B {
b: number;
}
const a: A = {a: 'dog', b: 'cat'}; // error, b is unknown property
const ab: A | B = {a: 'dog', b: 'cat'}; // no error!
您希望ab
出现'cat' is not a number
之类的错误,但由于上述问题,它不会出错。如果该问题得到解决,您的问题就会消失。
但我们不必等待。事实是对对象文字的多余属性检查不是非常保护。如果您向"fresh"对象文字添加未知属性,它会向您发出警告。在TypeScript中,向对象添加额外属性没有什么问题。如果对象是有效的A
,则即使您向其添加额外属性,该对象仍然是有效的A
。因此,如果你做了一些事情来逃避多余的属性检查(例如,为它分配一个“非新鲜”的文字),你就可以添加你想要的任何额外属性。
const dogCat = {a: 'dog', b: 'cat'};
const a: A = dogCat; // no error
如果您真的想要禁止额外的财产怎么办?好吧,没有general way为所有属性做这件事。但是如果你想禁止特定的额外属性并知道他们的密钥名称,那么就有办法:
interface A {
a: string;
b?: never; // cannot have a defined b
}
interface B {
b: number;
}
const dogCat = {a: 'dog', b: 'cat'};
const a: A = dogCat; // error, string is not undefined
const ab: A | B = {a: 'dog', b: 'cat'}; // error, string is not number
现在,您发现非新鲜a
和ab
都有错误。那么,回到你的情况......
如果我们可以假设TMessages
不能拥有controls
属性:
interface TMessages {
messages: TMessagesFormat;
controls?: never; // no defined controls
}
interface TGroupMessages {
messages?: TMessagesFormat;
controls: { [key: string]: TMessages | TGroupMessages }
}
然后,如果TMessages | TGroupMessages
具有已定义的controls
属性,则该属性必须是TGroupMessages
中指定的类型:
let tm: TMessages | TGroupMessages = {messages: {foo: 'hey'}, controls: 3}
// error, 'number' not assignable to type '{ [k: string]: TMessages | TGroupMessages }'
这应该对你有用。希望有所帮助;祝你好运!
等待Microsoft/TypeScript#22129解决,或将TMessages
界面更改为以下内容:
interface TMessages {
messages: TMessagesFormat;
controls?: never; // no defined controls
}