我试图定义一些基于基本类型的类型。
- “简单”类型具有名称和类型属性
- “Base”类型的属性名不能是“text”或“radio”
- 我创建了一个'Radio'和一个'Texto'类型
但是当我创建一个类型为:'radio',它不强制'radio'或'freq'属性...
我不知道为什么
有人能强调一下这个问题吗?
type Simple = {
name: string
type: string
}
type Base = Exclude<Simple, {type: 'text'|'radio'}>
type Radio = Base & {
type: 'radio',
radio: string,
freq: string
};
type Texto = Base & {
type: 'text'
label: string
}
type Field = Radio | Texto | Base
/**
* I expect to see an error thrown with 'freq' and 'radio' is missing here...
*/
const myRadio:Field = {
type: 'radio',
name:'snig'
}
1条答案
按热度按时间ymzxtsji1#
在TypeScript中,除了
"text"
和"radio"
之外,没有对应于所有string
值的特定类型,所以你不能给予Base
一个特定的类型来区分它与Texto
或Radio
。这将需要所谓的 * 否定类型 *,如在microsoft/TypeScript#29317中实现的,但从未发布。所以你不能说string & not ("text" | "radio")
。Exclude
实用程序类型只能过滤联合类型,但由于string
和Simple
都不是联合类型,因此它没有效果。如果没有特定的类型可以按照您想要的方式工作,您可以尝试generic类型并使用它来 * 约束 * 输入值。因此,您需要编写类似
const myRadio: Field<"radio"> = {⋯}
的代码,而不是const myRadio: Field = {⋯}
。或者,如果你不想手动编写类型参数,你可以编写一个实用函数来 * 推断 * 类型参数,而不是写const myRadio= field({⋯})
和myRadio
将其类型推断为Field<"radio">
。它可以看起来像这样:这里,
Field<T>
被实现为conditional type,它使用T
作为判别式来判别KnownField
(如果适用的话)(使用Extract
实用程序类型,否则回退到Simple
)。field()
是一个辅助函数,它可以提供您想要的推断。让我们试试看:
这就是你想要的错误。如果检查
myRadio
,则其类型为Radio
。下面的代码编译时没有错误:看起来不错
Playground链接到代码