我在一个项目中使用 typescript,在其中的某些部分我必须使用联合类型。但是我收到了一些我不知道如何处理的奇怪错误消息。 考虑以下类型:
type body = {
[_: string]:
| 'boolean'
| 'number'
| 'string'
| {
type: 'boolean' | 'number' | 'string'
optional?: boolean
}
| {
type: 'array'
items: 'boolean' | 'string' | 'number'
optional?: boolean
[_: string]: any
}
}
我使用 [_: string]:
是因为我应该可以使用任意键。该值可以是指示类型的字符串,也可以是提供更多详细信息的对象。
现在考虑以下函数:
function show(data: body) {
console.log(data)
}
当我用下面的对象调用上面的函数时:
const data = {
username: { type: 'string', optional: false },
address: { type: 'string' },
city: 'string'
}
打字稿给出以下错误:
<块引用>'{ username: { type: string; } 类型的参数可选:布尔值; };地址:{ 类型:字符串; };城市:字符串; }' 不能分配给 'body' 类型的参数。
<块引用>属性“用户名”与索引签名不兼容。
<块引用>输入'{类型:字符串;可选:布尔值; }' 不能分配给类型 '"string" | "数" | "布尔值" | { 类型:“字符串” | "数" | "布尔值";可选?:布尔值 |不明确的; } | { [_: 字符串]: 任何;类型:“数组”;项目:“字符串” | "数" | "布尔值";可选?:布尔值 |不明确的; }'。
<块引用>类型“{ type: string;”中缺少属性“items”可选:布尔值; }' 但需要在类型 '{ [_: string]: any;类型:“数组”;项目:“字符串” | "数" | "布尔值";可选?:布尔值 |不明确的; }'。
我该如何解决这个问题? 谢谢
答案 0 :(得分:3)
您可以明确声明您的属性 data
是什么类型
const data: body = {
username: { type: 'string', optional: false },
address: { type: 'string' },
city: 'string'
}
或投射它
const data = {
username: { type: 'string', optional: false },
address: { type: 'string' },
city: 'string'
} as body;
答案 1 :(得分:3)
这里的问题是对 data
变量类型的推断过于宽泛。看看reproduction here。
如果将鼠标悬停在 data
变量上,您会注意到它被赋予了推断类型:
{
username: {
type: string;
optional: boolean;
};
address: {
type: string;
};
city: string;
}
分解您的错误消息,我们看到第一行:
<块引用>属性“用户名”与索引签名不兼容。
表示 username
是这里的问题。从推断类型中可以看出,该属性的类型为 {type: string, optional: boolean}
。
您可能认为这与
{ type: 'boolean' | 'number' | 'string', optional?: boolean }
联合的一部分,但是关键区别在于联合的这一部分要求 type
属性具有文字字符串类型之一,并且 < em>不允许任何字符串(由类型 'boolean' | 'number' | 'string'
表示(不带引号))。
这就是为什么它然后尝试匹配您联合的最后一部分,由于索引签名,这将允许 string
键/值对。但是联合的最后一部分还需要一个 type: string
属性,这就是导致您看到的特定错误的原因。
那你是怎么解决的?那么你需要给打字稿一个提示,你的 Items
对象的 username.type
属性不仅仅是任何字符串。以下是一些不同的方法:
data
类型,如 Andreas 的出色回答。body
。您必须对所有三个属性执行此操作,因此在这种特殊情况下这不是很理想。type: 'string' as 'string'
const data = { ... } as const