使用TypeScript和fp ts进行类型建模,并在使用
我正在尝试使用TypeScript和使用TypeScript和fp ts进行类型建模,并在使用,typescript,functional-programming,fp-ts,Typescript,Functional Programming,Fp Ts,我正在尝试使用TypeScript和fp-ts来让我的脚在建模中湿透 域逻辑和类型,我遇到了这个问题: import { left, right, Either } from "fp-ts/lib/Either"; type MyType = { id: string, isValid: boolean, } type MyValidType = { id: string, isValid: true, } type CreateMyValidType = (t: MyTy
fp-ts
来让我的脚在建模中湿透
域逻辑和类型,我遇到了这个问题:
import { left, right, Either } from "fp-ts/lib/Either";
type MyType = {
id: string,
isValid: boolean,
}
type MyValidType = {
id: string,
isValid: true,
}
type CreateMyValidType = (t: MyType) => Either<Error, MyValidType>
// Compile error!
const createMyValidType: CreateMyValidType = t => {
switch (t.isValid) {
case true:
return right({
id: "test",
isValid: true
})
default:
return left(new Error())
}
}
当它在内部时,似乎无法识别正确的类型
我通过指定调用right
时的类型找到了避免问题的方法,但我不完全理解其含义,因此我不知道这是否是一个坏主意:
return right<Error, MyType2>({
id: "test",
isValid: true,
});
返回右键({
id:“测试”,
是的,
});
处理此问题并使其得以编译的正确方法是什么?
谢谢 简短回答
它在TS>=3.4中正常工作
回答稍微长一点
正如您可能已经注意到的那样,TypeScript通常并不擅长推理。
在代码示例中,您为函数的返回类型提供了注释,以便TS可以尝试将所有分支统一到预期的返回类型中:如果没有此显式注释,结果会更糟
即使使用手动类型注释,pre-3.4 TS也会“懒惰”,并尝试解析left
和right
函数声明的所有通用类型参数(两者都有L
和R
作为类型参数),而无需在做出选择之前“等待”获得更好的知识。
因此,对于default
案例,它将Error
推断为L
,对于true
案例,它将{id:string,isValid:boolean}
推断为R
。问题是MyValidType
要求isValid
为文本true
(比boolean
更具体),因此它最终以失败告终
Type '{ id: string; isValid: boolean; }' is not assignable to type 'MyValidType'.
Types of property 'isValid' are incompatible.
Type 'boolean' is not assignable to type 'true'.
使用TS>=3.4
时,R
将一直处于“未决定”状态,直到过程的后期,当TS实际知道createMyValidType
的预期(注释)返回类型,并正确地将文本对象视为可分配给声明的返回类型
您可以在官方的变更日志中阅读更多关于此改进的内容,网址为
附注1
该问题实际上与fp ts
无关,因为在3.4之前,任何通用函数都会出现类似问题:
declare function identity<T>(t: T): T;
function f(): { foo: 'foo' } {
return identity({ foo: 'foo' });
}
// Type '{ foo: string; }' is not assignable to type '{ foo: "foo"; }'.
// Types of property 'foo' are incompatible.
// Type 'string' is not assignable to type '"foo"'.
考虑到JS的易变性,这是一个“安全”默认值。可以使用“const
断言”更改此行为:
这是3.4
(请参阅)中的另一个添加项,在您的示例中,由于在createMyValidType
中有返回类型注释,因此不严格需要它
declare function identity<T>(t: T): T;
function f(): { foo: 'foo' } {
return identity({ foo: 'foo' });
}
// Type '{ foo: string; }' is not assignable to type '{ foo: "foo"; }'.
// Types of property 'foo' are incompatible.
// Type 'string' is not assignable to type '"foo"'.
const foo = 'foo' // Type: "foo"
const fooObj = { foo: 'foo' } // Type: { foo: string }
const fooObj = { foo: 'foo' } as const // Type: { readonly foo: "foo" }