我想实现一个可以通过不同参数推断返回类型的函数。
直接调用时可以正常推断类型,但使用函数返回参数时,会推断不正确。
以下是我写的重载代码:
export interface Option {
init?: boolean
test?: boolean
}
function getType(): string
function getType(option: Record<string, never>): string
function getType(option: Option & { init: true }): boolean
function getType(option: Option & { init: false }): string
function getType(
option?: Option,
): Option extends { init: true } ? boolean : string
function getType(option?: Option): boolean | string {
if (option?.init) {
return true
} else {
return 'none'
}
}
getType() // string
getType({}) // string
getType({
init: true,
}) // boolean
getType({
init: false,
}) // string
getType({
test: false,
}) // string
function useGetType(opt?: Option) {
return getType(opt)
}
// What should be inferred here is boolean
useGetType({ init: true }) // string ???
问题是:
function getType(
option?: Option,
): Option extends { init: true } ? boolean : string
这种类型永远不能是布尔值。为什么?因为
Option
永远无法延伸
{init: true}
。
让我们暂时忽略
test
字段,只考虑 init
字段。如果我们用 const m : Option = { init :false }
定义一个对象,我们不能将它分配给 {init : true}
。因此扩展失败。
这就是为什么:
function useGetType(opt?: Option) {
return getType(opt)
}
永远不能返回布尔值,因为这里的
getType(opt)
不能返回boolean
。
我设置了一个小演示来给你一个想法:
export interface Option {
init: boolean
}
export interface WithInit {
init : true
}
//Check this type
type T = Option extends { init: true } ? boolean : string;
const m1 : Option = Math.random() > 0.5 ? { init : true } : { init : false };
const m2 : Option = { init : true };
const n1 : WithInit = m1; //will error out
const n2 : WithInit = m2; //will error out