我想定义一个接口,不允许分配'选项'字符串的configNames字段,但无法弄清楚如何使其工作:
// First try
interface Options<T = string> {
configNames: T extends 'options' ? never: string;
}
// No validation because 'options' is subset of string, thus the type is always false, thus configName type is string
const options: Options = {
configNames: 'options'
}
// Second try
interface Options<T> {
configNames: T extends 'options' ? never: string;
}
// typescript error: Generic type 'Options<T>' requires 1 type argument(s).
const options: Options = {
configNames: 'options'
}
是否有任何变通方案来实现这一点?
1条答案
按热度按时间goucqfw61#
TypeScript中没有与“除
"options"
之外的所有string
“对应的特定类型。这将需要类似于microsoft/TypeScript#4196中建议的 negated types 的内容(甚至在从未合并的microsoft/TypeScript#29317中实现)。如果TypeScript对类型取反,那么您大概可以编写类似string & not "options"
的代码。但它没有。如果使用特定的Options
类型是一个要求,那么您想要的是目前不可能的。因此,您只剩下一些变通方法:没有特定的类型,但是可以将
Options<T>
设置为generic类型(如第一次尝试所示),然后将其用作候选类型的 * 约束 *。您可以编写一个帮助函数来为您推断泛型类型参数T
。因此,虽然无法编写const o: Options = {...}
并使其按预期行为,您 * 可以 * 编写const o = options({...})
并获得类似的效果(如果您斜视它们,它们实际上并没有太大的不同)。我们的想法是使用conditional types从
T
中的任何字符串类型中过滤掉"options"
,你可以使用Exclude<T, U>
实用程序类型来完成这个任务:这与您的版本类似。另外,如果您想禁止
string
本身(这样{configNames: someRandomString}
就会被拒绝,因为它可能是"options"
),您也可以扩展定义来实现这一点:这取决于你是更关心误报还是漏报。
现在您可以进行测试:
看起来不错。您得到了您所关心的验证。它与您所期望的方法有些不同,但它有可能实现的好处。
Playground代码链接