2021年6月13日:已更新至TS4.1+
不完全是在编译时,没有。有一个
建议(现在在microsoft/TypeScript#41160)允许正则表达式验证的字符串类型,但不清楚它是否会被实现。如果您想去那个建议并提供一个令人信服的用例,这可能有所帮助(但也可能没有真正的帮助)。
您可以
尝试使用
模板文字类型来以编程方式生成匹配每个可接受的字符串字面量的大
联合。如果您只需要三个左右的数字,这甚至有点起作用。
type UCaseHexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
'8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
type HexDigit = UCaseHexDigit | Lowercase<UCaseHexDigit>
type ValidThreeDigitColorString = `#${HexDigit}${HexDigit}${HexDigit}`;
但是由于这种模板文字类型只能处理成员数量在数万个左右的联合类型,如果您尝试使用六位数字,它将会出现错误:
type ValidSixDigitColorString =
`#$$$$$$`;
所以你需要使用一个变通方法。
一种解决方法是使用模板字面量类型作为
通用约束,而不是将
ValidColorString
作为具体类型。相反,有一个类型
AsValidColorString<T>
,它接受一个字符串类型的
T
并对其进行
检查以查看它是否有效。如果是,则保持不变。如果不是,则返回一个与错误值“接近”的有效颜色字符串。例如:
type ToHexDigit<T extends string> = T extends HexDigit ? T : 0;
type AsValidColorString<T extends string> =
T extends `#$$$$$$` ?
`#$$$$$$` :
T extends `#$$$` ?
`#$$$` :
'#000'
const asTextProps = <T extends string>(
textProps:
) => textProps;
这很复杂,主要是将字符串T
拆分并检查每个字符,将不良字符转换为0
。然后,您不会将某些东西注释为TextProps
,而是调用asTextProps
进行验证:
const textProps = asTextProps({
color: "#abc"
})
const badTextProps = asTextProps({
color: "#00PS1E"
})
这在编译时可以工作,但可能会带来更多的麻烦。
最后,您可以退回到TS4.1之前的解决方案,并使用用户定义类型保护创建一个类似名义类型的string
子类型,以缩小string
值范围...然后跳过各种障碍来使用它:
type ValidColorString = string & { __validColorString: true };
function isValidColorString(x: string): x is ValidColorString {
const re = /#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?/g;
return re.test(x);
}
使用方法:
const textProps: ITextProps = {
color: "#abc"
};
const color = "#abc";
if (isValidColorString(color)) {
const textProps2: ITextProps = {
color: color
};
} else {
throw new Error("The world has ended");
}
后者并不完美,但至少让您更接近实施这些约束。
希望这能给您一些想法,祝你好运!
代码的Playground链接