Отличается ли типовые параметры в typescript?

TypeScript позволяет передавать различные параметры типа, например:

public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) {}

Но то, что я функционирую внутри, ожидает только типа параметра SchoolClass[] для classes?

this.functionInside(classes: SchoolClass[], true)

Обязательно ли указывать тип ClassesAndSubjects[] | SchoolClass[] и для функции внутри?

Это заставляет дублировать код.

если this.functionInside принимает только тип SchoolClass[], то почему вы используете тип объединения как classes: ClassesAndSubjects[] | SchoolClass[]

Niladri 11.04.2018 13:10
0
1
31
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас может быть функция, которая принимает тип объединения и вызывает внутри функцию, которая принимает только один из них, вам нужно использовать только тип охранник, так что эта функция вызывается только тогда, когда истинный тип аргумента - это то, что функция ожидает:

public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) {
    if (classes && (classes[0] instanceof SchoolClass)) {
       // we can safely call functionInside:
       functionInside(classes as SchoolClass[]);
    } else { 
       // ... something ...
    }
}

Это работает, если ClassesAndSubjects и SchoolClass являются классами. Если бы это были интерфейсы, вы не смогли бы использовать instanceof, поэтому вам придется использовать защиту другого типа. Например, если SchoolClass имеет свойство someProp, которого нет у ClassesAndSubjects:

public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) {
    if (classes && classes[0] && ('someProp' in classes[0])) {
       // we can safely call functionInside:
       functionInside(classes as SchoolClass[]);
    } else { 
       // ... something ...
    }
}

Третий вариант - определение истинного тип охранник:

function isSchoolClassArray(x: any[]): x is SchoolClass[] {
    return (x !== null && x.length > 0) ? ('someProp' in x[0]): false;
}

public getClassesNumbers(classes: ClassesAndSubjects[] | SchoolClass[]) {
    if (isSchoolClassArray(classes)) {
       // we can safely call functionInside:
       functionInside(classes);
    } else { 
       // ... something ...
    }
}

Преимущество последнего варианта в том, что TypeScript будет знать, какой тип classes находится внутри if и else, поэтому нет необходимости в утверждениях типа.

Конечно, в обоих этих случаях, если массив пуст, защита типов не сработает, но в этом случае это не имеет значения, потому что functionInside также получит пустой массив.

Другие вопросы по теме