打字稿中"one level deep"区分联合的类型缩小



我无法获得以下类型检查:

type Apple = {
variety: {type: 'fuji'} | {type: 'gala'}
}
type FujiApple = {
[P in keyof Apple]: P extends 'variety'
? Extract<Apple['variety'], {type: 'fuji'}>
: Apple[P]
}
function fujiFn(fugi: FujiApple) {}
function appleFn(apple: Apple) {
if (apple.variety.type === 'fuji') {
// FAILS: Argument of type 'Apple' is not assignable to parameter of type
// 'FujiApple'
fujiFn(apple)
}
}

是否有一种方法可以输入这个以使缩小工作如期进行?只有当鉴别符不在顶层时才会发生这种情况。

我不喜欢的方案:

下面的内容实际上是有效的,但是它是…我宁愿不这样做。

fujiFn({...apple, variety:apple.variety})

你可以使用typeguard:

function isFujiApple(arg: Apple): arg is FujiApple {
return arg.variety.type === 'fuji';
}
function appleFn(apple: Apple) {
if (isFujiApple(apple)) {
fujiFn(apple); // Now it works
}
}

我认为TS存在问题,因为它无法推断联合的嵌套属性。

解决方案如下:


type Fuji = { type: 'fuji' }
type Gala = { type: 'gala' }
type Variety = Fuji | Gala
type Apple = {
variety: Variety
}
type FujiApple = {
[P in keyof Apple]: P extends 'variety'
? Extract<Apple['variety'], { type: 'fuji' }>
: Apple[P]
}

function fujiFn(fugi: FujiApple) { }

function appleFn(apple: Variety) {
if (apple.type === 'fuji') {
fujiFn({ variety: apple }) // ok
}
}

最新更新