Константные утверждения TypeScript: как использовать Array.prototype.includes? - PullRequest
0 голосов
/ 12 июня 2019

Я пытаюсь использовать массив элементов в качестве объединяющего типа, что стало проще с константными утверждениями в TS 3.4, поэтому я могу сделать это:

const CAPITAL_LETTERS = ['A', 'B', 'C', ..., 'Z'] as const;
type CapitalLetter = typeof CAPITAL_LETTERS[string];

Теперь я хочу проверить, является ли строка заглавной буквой, но следующее не с «не присваивается параметру типа»:

let str: string;
...
CAPITAL_LETTERS.includes(str);

Есть ли лучший способ исправить это, вместо приведения CAPITAL_LETTERS к unknown, а затем к Array<string>?

1 Ответ

1 голос
/ 25 июня 2019

Стандартная подпись библиотеки для Array<T>.includes(u) предполагает, что проверяемое значение имеет тот же или более узкий тип, что и элементы массива T.Но в вашем случае вы делаете обратное, сверяясь со значением типа wider .Фактически, единственный раз, когда вы скажете, что Array<T>.includes<U>(x: U) является ошибкой и должна быть запрещена, это если нет перекрытия между T и U (т. Е. Когда T & U равно never).

Теперь, если вы не собираетесь делать подобное "противоположное" использование includes() очень часто, и вам нужны нулевые эффекты во время выполнения, вам просто нужно расширить CAPITAL_LETTERS до ReadonlyArray<string> черезвведите assertion:

(CAPITAL_LETTERS as ReadonlyArray<string>).includes(str); // okay

Если, с другой стороны, вы достаточно серьезно чувствуете, что это использование includes() должно быть принято без утверждений типа, и вы хотите, чтобы это происходило во всем вашем коде,Вы могли бы объединить в пользовательском объявлении :

// global augmentation needed if your code is in a module
// if your code is not in a module, get rid of "declare global":
declare global { 
  interface ReadonlyArray<T> {
    includes<U>(x: U & ((T & U) extends never ? never : unknown)): boolean;
  }
}

Это сделает так, что массив (ну, конечно, массив только для чтения, но это то, что у вас есть в этом примере) позволит любомупараметр для .includes(), если между типом элемента массива и типом параметра есть некоторое перекрытие.Так как string & CapitalLetter не never, он разрешит звонок.Это все равно будет запрещать CAPITAL_LETTERS.includes(123), однако.

Хорошо, надеюсь, это поможет;удачи!

...