如何使TypeScript区分模板文字字符串和任何其他字符串



游乐场链接

我有一个函数,它接受第二个参数,当第一个参数是与模板文本字符串匹配的字符串时,该参数仅是所需的。然而,似乎即使TypeScript知道第一个参数是这样的字符串,它仍然匹配采用常规字符串的重载:

type KnownString = `known${string}`;
type AnyString = string;
function doSomethingWithString(arg1: KnownString, onlyRequiredForKnownString: boolean): string;
function doSomethingWithString(arg1: AnyString, onlyRequiredForKnownString?: boolean): string;
function doSomethingWithString(arg1: KnownString | AnyString, onlyRequiredForKnownString?: boolean): string {
return "The second argument is only required when `arg1` is a KnownString";
}
const thisIsAKnownString = "knownstring" as KnownString;
// @ts-expect-error Since TS knows that arg1 is a KnownString, it should require the second parameter:
doSomethingWithString(thisIsAKnownString);

这当然是有道理的,因为它一个正则字符串。有没有一种方法可以告诉重载匹配除KnownString之外的任何常规字符串

(我确实尝试了类似问题中建议的条件类型,但这似乎不适用于模板文本字符串。(

我相信您不需要重载您的函数。

考虑下一个例子:

type IsKnown<T extends string> = T extends `known${string}` ? true:false
type Validator<T extends boolean> = 
T extends true 
? [] 
: [boolean];
function validation<Str extends string>(arg1: Str, ...validation: [...Validator<IsKnown<Str>>]): string {
return "The second argument is only required when `arg1` is a KnownString";
}
const knownstring = "knownstring";
validation(knownstring); // does not require second argument
validation('unknown'); // requires second argument

游乐场

请记住,function foo(a:number,...args:[]){}评估为function foo(a:number){}

MO关于这种方法的更多信息,你可以在我的博客中找到

考虑到,你可以组成你的验证器:

type IsKnown<T> = T extends `known${string}` ? true : false
type StringNumber<T> = T extends `${number}` ? true : false

type Validator<T extends boolean> =
T extends true
? []
: [boolean];

function validation<Str extends string>(arg1: Str, ...validation: Validator<StringNumber<Str>> | Validator<IsKnown<Str>>): string {
return "The second argument is only required when `arg1` is a KnownString";
}
const knownstring = "knownstring";
validation(knownstring); // does not require second argument
validation('2234'); // does not require second argument, because it is number
validation('wer'); //  requires second argument, because it is number

我确实找到了另一个具有函数重载和更简单类型的解决方案:

type KnownString = `known${string}`;
type AnyString = string;
type NotKnown<T extends AnyString> = T extends KnownString ? never : T;
function doSomethingWithString(arg1: KnownString, onlyRequiredForKnownString: boolean): string;
function doSomethingWithString<T extends AnyString>(arg1: T & NotKnown<T>): string;
function doSomethingWithString(arg1: KnownString | AnyString, onlyRequiredForKnownString?: boolean): string {
return "The second argument is only required when `arg1` is a KnownString";
}
const thisIsAKnownString = "knownstring" as KnownString;
// @ts-expect-error Since TS knows that arg1 is a KnownString, it should require the second parameter:
doSomethingWithString(thisIsAKnownString);

游乐场链接。

相关内容

最新更新