簡體   English   中英

TypeScript:鍵入以包含來自預定義集的任何值EXCEPT值

[英]TypeScript: Type to contain any value EXCEPT values from a predefined set

是否可以使用包含任何值的類型但是來自預定義集合的值?

type Fruit = 'Apple' | 'Banana' | 'Orange'
type NotFruit = ???

const a: NotFruit = 'Carrot'; // Compiler OK.
const b: NotFruit = 'Apple';  // Compiler ERROR.

即是否存在NotFruit的定義, NotFruit編譯器根據我的代碼中的注釋進行響應?

我會回答說這絕對不可能使用Typescript。 語言中的集合沒有否定運算符。

您可以創建一個instanceOf typeguard。

https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

type Fruit = "Apple" | "Orange";

function isFruit(fruit: string): fruit is Fruit {
    return !(['Apple', 'Orange'].includes(fruit));
}

TypeScript目前不支持否定類型作為具體類型,但也許它們有一天會被支持。

目前,表達否定類型的唯一方法是間接地 ,通過驗證條件是否滿足的泛型類型。

就像是:

type DefinitelyNot<T, C> = [T] extends [C]
  ? Invalid<[C, "is prohibited because it might be", T]>
  : [C] extends [T]
    ? Invalid<[C, "is prohibited because it is assignable to", T]>
    : C;

類型DefinitelyNot<T, C>采用類型T否定,並采用候選類型C 如果我們可以確定CT 兼容,那么我們返回C本身。 否則,我們返回C將不匹配的內容,特別是導致錯誤的Invalid類型。 好了,我們這么做,如果無效類型提供了支持 ,這是他們目前還沒有。 所以我們也需要一個解決方法:

type Invalid<Msg> = Msg & Error;

它會產生一些相當丑陋的錯誤消息,但至少開發人員可能有機會弄清楚錯誤出現的原因。 然后我們可以創建一個帶有類型T函數,並生成一個只接受與T不兼容的參數的新函數:

const makeNot = <T>() => <C>(val: C & DefinitelyNot<T, C>): C => val;

我們來試試吧:

type Fruit = "Apple" | "Banana" | "Orange";

const asNotFruit = makeNot<Fruit>();

const a = asNotFruit("Carrot"); // okay
const b = asNotFruit("Apple"); // error
//  ┌--------------> ~~~~~~~ 
// ["Apple", "is prohibited because it is assignable to", Fruit]

function someRandomFunction(x: string, y: number) {
  const c = asNotFruit(x); // error
  // ┌---------------> ~
  // [string, "is prohibited because it might be", Fruit]
  const d = asNotFruit(y); // okay (a number cannot be Fruit)
}

正如你所看到的, "Carrot"number被接受了,因為那些絕對不是Fruit "Apple"被拒絕了,因為它肯定 Fruit ,並且string被拒絕,因為它可能是 Fruit

不確定你是否想要使用這種解決方案,但我想我還是要包含它。 希望有所幫助。 祝好運!

鏈接到代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM