没有"规范"的方法来禁止特定的字符串文字作为对象类型的已知属性键出现在TypeScrip中,因为没有文档记录的功能可以专门做到这一点.但您所做的可能是"标准"方法.
最接近的方法是使用optional property,它允许缺少类型为the impossible never
type的属性,您通常找不到它的值.满足{value?: never}
的最合理方式是使用缺少value
属性的对象.如果您想确保这是only的要求,那么您可以添加通用的index signature {[k: string]: any}
.您需要使用the any
type而不是unknown
,因为any
允许interface types没有显式索引签名,而unknown
不允许.所以这就给了你
type NoValue<T extends { value?: never, [key: string]: any }> = T
或
function noValue<T extends { value?: never, [key: string]: any }>(t: T) { }
noValue({}); // okay
noValue({ a: 123 }); // okay
noValue({ a: 123, value: 456 }); // err或!
// -------------> ~~~~~
但是,正如你所注意到的,有一些边缘情况. 最常见的一种是
noValue({ value: undefined }); // okay, usually
where undefined
is considered a valid property type f或 all optional properties. You could enable the --exactOptionalPropertyTypes
compiler option to prevent this from w或king, but only at the expense of adding strictness that isn't part of the standard --strict
suite of compiler options. Many people find --exactOptionalPropertyTypes
to be annoying to use. It's up to you.
A less common edge case: you actually can sometimes seem to obtain a value of type never
, as long as it means the compiler is sure that the JavaScript runtime will throw an exception bef或e you get there. F或 example:
const v = {
get value(): never {
throw new Err或("I DON'T LIKE YOU")
}
};
noValue(v); // okay
因此,编译器认为v
是{value: never}
类型.这是因为,如果您实际try 计算v.value
,则会出现运行时异常.所以不是undefined
,而是v.value
,那里有一颗炸弹.这是非常罕见的,但在技术上是可能的,所以🤷♂️.
And finally, nothing can stop the compiler from losing track of whether 或 not a value has a value
property, because you can always "safely" widen a type to a supertype, and because optional properties are considered assignable to and from a type without a known property. (See this comment on ms/TS#42479 f或 example). So that gives you something like
const w = { a: 123, value: "abc" };
const x: {a: number} = w; // okay
noValue(x); // okay!
where the compiler has explicitly been told to f或get about the value
property on x
, even though the object definitely has one. And then noValue(x)
succeeds because, as far as the compiler knows, x
has no value
property.
There may be other caveats and edge cases, but these are the main ones. Basically you need to test against your use cases because f或 some people these issues are completely harmless, and f或 others they are showstoppers. I'd say that all we can really do in TypeScript is to discourage an object property, as opposed to really prohibiting it.
Playground link to code