Во время выполнения нет разницы между Array<Foo>
и Array<Bar>
; система типа stati c стерта из испущенного JavaScript, поэтому у вас есть только массив JavaScript. Поэтому вам нужно написать свой собственный тест, который работает во время выполнения, а затем сообщить компилятору о том, что вы делаете, чтобы получить преимущества от stati c typing.
Одним из способов было бы напишите несколько подходящих пользовательских функций защиты типов , которые позволят вам сделать это:
public format(value: Foo[] | Bar[]) {
const isFooArray = isArrayOf(isInstanceOf(Foo));
if (isFooArray(value)) {
// true block
for (const foo of value) {
const f: Foo = foo; // okay
}
} else {
// false block
for (const bar of value) {
const b: Bar = bar; // okay
}
}
}
Компилятор понимает, что внутри истинного блока value
было сужено от Foo[] | Bar[]
до Foo[]
, а внутри ложного блока value
было сужено с Foo[] | Bar[]
до Bar[]
. Это связано с сигнатурой типа для isFooArray()
, охранника типов, созданного путем объединения выходных данных двух других функций, isArrayOf()
и isInstanceOf()
.
Давайте рассмотрим их определения:
const isArrayOf = <T>(elemGuard: (x: any) => x is T) =>
(arr: any[]): arr is Array<T> => arr.every(elemGuard);
Функция isArrayOf()
принимает функцию защиты типов elemGuard
для одного элемента массива и возвращает защиту нового типа, которая вызывает elemGuard
для каждого элемента массива. Если все элементы проходят тест, то у вас есть массив охраняемого типа. Если хотя бы один элемент не проходит, значит, нет. При желании вы можете проверить только один элемент, но вы рискуете случайно обработать гетерогенный массив, такой как Array<Foo | Bar>
, как Foo[]
. Также обратите внимание, что это означает, что пустой массив []
всегда будет проходить тест; поэтому пустой массив будет считаться Foo[]
и a Bar[]
.
const isInstanceOf = <T>(ctor: new (...args: any) => T) =>
(x: any): x is T => x instanceof ctor;
Функция isInstanceOf()
просто оборачивает обычный тест instanceof
в пользовательский определенный тип защиты подходит для использования с isArrayOf()
.
Итак, const isFooArray = isArrayOf(isInstanceOf(Foo))
- это защита составного типа, которая специально проверяет, является ли проверяемый массив Foo[]
, проверяя каждый элемент и выполняя проверку instanceof
.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код