#typescript
#машинописный текст
Вопрос:
Просто прочитайте о Type Guards
главе в Typescript
Но почему мои следующие простые типы охранников не могут различить объединение enum?
enum A {
COMMA = ',',
PLUS = ' '
}
enum B {
REAL = 'REAL',
STRING = 'STRING'
}
function notWork<T extends A | B>(val: T) {
if(isA(val)) {
// mark 1:
console.log('isA:', useA(val))
} else {
// mark 2:
// val should be in type B here !!!
console.log('isB:', useB(val))
}
}
function isA(token : A | B): token is A {
return Object.values(A).includes(token as A)
}
function useA(v: A) {
console.log("we're using A:", v)
return v
}
function useB(v: B) {
console.log("we're using B:", v)
return v
}
в моем понимании:
- в mark 1 значение val на самом деле находится в type:
(T amp; A.COMMA) | (T amp; A.PLUS)
. это работает, но почему это не простойA
- в mark 2 вэл по-прежнему
A | B
, почему мои охранники типа потерпели неудачу?
Ответ №1:
Это потому isA(x) === false
, что не означает, что x
это a B
, просто это не an A
.
enum C {
FOO = 'FOO',
BAR = 'BAR'
}
function notWork<T extends A | B>(val: T) { // yes, not A | B | C
function isA(token : A | B | C): token is A {
Приводит к ошибке того же типа, но теперь понятно, почему isA
это не означает, что это a B
и не может быть a C
.
Ваш isA
метод может принимать любое объединение типов в качестве параметра. Это отличается от T
in notWork
.
Теперь, если вы передаете оба одинаковых типа, внезапно компилятор знает, что любой T
, который не является an, A
должен быть a B
:
type T = A | B
function notWork(val: T) {
function isA(token : T): token is A {
Ответ №2:
Изменить подпись с:
function notWork<T extends A | B>(val: T) { // ...
Для:
function notWork(val: A | B) { // ...
И все будет работать так, как вы ожидали.