排除特定字符串以外的类型

huangapple go评论68阅读模式
英文:

Excluding specific strings from type

问题

type TestName = 'test1' | 'test2' | 'test3';

type CustomName = `${string}` /// 需要排除 TestName

const name: CustomName = 'test'; // 允许
const name: CustomName = 'test1'; // 不允许
const name: CustomName = 'test2'; // 不允许
const name: CustomName = 'test3'; // 不允许
英文:

If I have a type as:

type TestName = 'test1' | 'test2' | 'test3';

How do I define a type of string with not the above?

type CustomName = `${string}` /// need to exclude TestName

const name: CustomName = 'test'; // allowed
const name: CustomName = 'test1'; // not allowed
const name: CustomName = 'test2'; // not allowed
const name: CustomName = 'test3'; // not allowed

答案1

得分: 0

就像 @Alex 说的,目前在 TypeScript 中似乎不可能实现。然而,你可以对函数参数做类似的操作:

type TestName = 'test1' | 'test2' | 'test3';

type NotTestName<T> = T extends TestName ? never : T;
function myFunc<T>(myValue: NotTestName<T>) {}

现在,调用这个函数的关键部分是确保将值缩小为 string 类型,因为实际上它不在 TestName 类型中,因此它会通过测试:

// 允许
myFunc('test' as const);
myFunc('abc' as const);

// 不允许
myFunc('test1' as const);
myFunc('test2' as const);
myFunc('test3' as const);

最终,如果你需要一个像在你的帖子中那样的最终常量值,你可以将它用作辅助函数:

type TestName = 'test1' | 'test2' | 'test3';

type NotTestName<T> = T extends TestName ? never : T;
function h<T>(value: NotTestName<T>): T { return value; }

// 允许
const name = h('test' as const);

// 不允许
const name = h('test1' as const);
const name = h('test2' as const);
const name = h('test3' as const);

你可以在这个 playground 中运行它

请记住,如果字符串没有被缩小,测试将会错误地通过。

英文:

Like @Alex said, it doesn't seem to be possible with current TS. However, you can do something similar for a function parameter:

type TestName = &#39;test1&#39; | &#39;test2&#39; | &#39;test3&#39;;

type NotTestName&lt;T&gt; = T extends TestName ? never : T;
function myFunc&lt;T&gt;(myValue: NotTestName&lt;T&gt;) {}

Now, the key part on calling this function is to ensuring you get the value narrowed as string is, indeed, not in the TestName type and, therefore, it would pass the test:

// Allowed
myFunc(&#39;test&#39; as const);
myFunc(&#39;abc&#39; as const);

// Not allowed
myFunc(&#39;test1&#39; as const);
myFunc(&#39;test2&#39; as const);
myFunc(&#39;test3&#39; as const);

Ultimately, if you need a final const value like in your post, you can use it as helper function:

type TestName = &#39;test1&#39; | &#39;test2&#39; | &#39;test3&#39;;

type NotTestName&lt;T&gt; = T extends TestName ? never : T;
function h&lt;T&gt;(value: NotTestName&lt;T&gt;): T { return value; }

// Allowed
const name = h(&#39;test&#39; as const);

// Not allowed
const name = h(&#39;test1&#39; as const);
const name = h(&#39;test2&#39; as const);
const name = h(&#39;test3&#39; as const);

You can run it in this playground.

Remember that if the string is not narrowed, you will get the test to wrongly pass.

huangapple
  • 本文由 发表于 2023年2月14日 00:14:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75438479.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定