如何在打字稿中实现函数式语言"Either"功能



在函数式语言中,我可以定义一个方法,其中签名明确表示该方法返回类型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)

我在谷歌上搜索了一下,找到了这个帖子,但我仍然不明白为什么x的类型总是假的?如果您传递了一个负数,那么我的代码将返回AppError对象,在这种情况下,typeof result3 === 'AppError'的值应该为true。

typeof在JavaScript和TypeScript中不返回类名或构造函数名,但它只返回本机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' );
}

这个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.
}

最新更新