是否可以定义一个类型,该类型可以分配除少数几个指定的字符串值之外的所有字符串值?我想根据这个(未编译的)示例表达一些东西:
type ReservedNames = "this" | "that"
type FooName = string - ReservedNames;
const f1 : FooName = "This" // Works
const f2 : FooName = "this" // Should error
答案 0 :(得分:4)
如果将具体的字符串值作为模板参数添加到FooName
,则可能不需要接受的答案就不需要辅助功能。
type ReservedNames = "this" | "that"
type NotA<T> = T extends ReservedNames ? never : T
type NotB<T> = ReservedNames extends T ? never : T
type FooName<T> = NotA<T> & NotB<T>
const f1: FooName<'This'> = 'This' // works
const f2: FooName<'this'> = 'this' // error
const f3: FooName<string> = 'this' //error
const f4: FooName<any> = 'this' // error
const f5: FooName<unknown> = 'this' // error
并且在函数中,您仍然可以仅通过对函数进行模版化就可以在不知道其值的参数上使用它。
function foo<T extends string> (v: FooName<T>) {
...
}
foo('this') // error
foo('This') // works
答案 1 :(得分:1)
对于此问题没有通用的解决方案,因为没有办法在打字稿类型系统中表达字符串可以是除列表以外的任何值的事实。 (有人可能会认为条件类型// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(targetLength,padString) {
targetLength = targetLength>>0; //truncate if number or convert non-number to 0;
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength) {
return String(this);
}
else {
targetLength = targetLength-this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed
}
return padString.slice(0,targetLength) + String(this);
}
};
}
可以起作用,但不会起作用,它只返回字符串即可。)
作为一种变通方法,如果我们有一个函数,并且我们特别希望不允许传入某些常量,我们可以使用条件类型来检查Exclude<string, ReservedNames>
,并且如果传入的参数为{{ 1}},然后以实际上无法满足的方式键入输入参数(使用交集类型)。
ReservedNames
答案 2 :(得分:0)
我用以下方法解决了这个问题:
Literals
的对象,它是文字的联合。ExcludedLiterals
类型中的任何文字,它是 Literals
的子集。keyof
分辨率。type OmitLiteral<Literals extends string | number, ExcludedLiterals extends Literals> = keyof Omit<{ [Key in Literals]: never }, ExcludedLiterals>;
有点复杂,但它有效。
type BaseUnion = "abc" | "def" | "ghi"; // "abc" | "def" | "ghi"
type OmittedUnion = OmitLiteral<BaseUnion, "ghi">; // "abc" | "def"