Как реализовать функциональность «Либо» функционального языка в машинописи - PullRequest
0 голосов
/ 12 апреля 2020

В функциональных языках я могу определить метод, в котором сигнатура четко говорит, что либо метод возвращает тип A или тип B. например:

class AppError(message: String)
public convertToString(input: Int) : Either[AppError, String]

Левая сторона - это всегда неудовлетворительный путь, и правая сторона - это счастливый путь. Я пытаюсь сделать что-то подобное в машинописи. Я написал этот код

type AppError = {message: String, errorCode: number}
function doSomething(param1: number) : AppError | string {
  if (param1 < 0) {
    return {"message": "param1 cannot be less than 0"}
  } else {
    return +param1
  }
}
const result3 = doSomething(-1)
if (typeof result3 === "AppError") {
  console.log("got this exception" + result3.message)
} else 
  console.log("got result " + result3)
}

Но компилятор машинописного текста говорит:

This condition will always return 'false' since the types '"string" | "number" | "bigint" | 
"boolean" | "symbol" | "undefined" | "object" | "function"' and '"AppError"' have no 
overlap.ts(2367)

Я погуглил и нашел этот поток, но я до сих пор не понимаю, почему typeof х всегда быть ложным? Мой код возвращает объект AppError, если вы передаете отрицательное число, и в этом случае typeof result3 === 'AppError' должно иметь значение true.

1 Ответ

1 голос
/ 12 апреля 2020

typeof в JavaScript, и TypeScript не возвращает имя класса или имя конструктора, но возвращает только native JavaScript значение-типа-имени, которое только один из:

'string'
'number'
'bigint'
'boolean'
'symbol'
'undefined'
'object'        // Note that `typeof aNullVar` evalutes to `'object'` btw.
'function'

То, что вы хотите, это TypeScript защита типа функция , которая используется для проверки типа во время выполнения, что компилятор будет "доверять" для обеспечения безопасности типов.

Обратите внимание, что тип возвращаемого значения isAppError ниже value is AppError.

Например:

function isAppError( value: string | AppError ): value is AppError {
    return typeof value === 'object'
        && ( value !== null )
        && ( 'message' in value )
        && ( 'errorCode' in value )
        && ( typeof (value as AppError).errorCode === 'number' );
}

This isAppError Функция, вероятно, может быть упрощена (например, вам не нужна проверка value !=== null, если вы находитесь в строгом режиме.

И используется так:

if( isAppError( result3 ) ) {
    // TypeScript *knows* that `result3` is of-type `AppError` inside this `if` statement's scope.

    console.log( result3.errorCode ); // TypeScript knows that result3 is AppError here.
}
else {
    // If `result3`'s type is an intersection type of only 2 types then TypeScript *knows& that result3 is of-type `string` inside this `else` statement's scope.

    console.log( result3.substring(1) );  // TypeScript knows that result3 is string here.
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...