Closed4
TypeScript 5.8 で conditional type の戻り値がNarrowingできるそうなので試す

この制限に合致されている必要があるとのこと。
function f<T extends A | B>(x: T):
T extends A ? string :
T extends B ? number :
never

例えば Result型みたいなケース
TypeScript5.7
Success<T> | Failure
を戻り値にして型アサーション、型ガードによってNarrowingが必要だった
type Success<T> = { data: T, isResult: 'Success' }
type Failure = { isResult: 'Failure' }
type ObjectValues = Record<'data', unknown> | Record<'error', unknown>
const maybeHasData = <T extends ObjectValues>(value: T): Success<T> | Failure => {
if ('data' in value) {
return { ...value, isResult: 'Success' } as Success<any>
}
return { isResult: 'Failure' } as Failure
}
const result1 = maybeHasData({ data: 'foo' }) // Failure | Success<{ data: string; }>
if (result1.isResult === 'Success') {
console.log(result1.data) // Success<{data: string;}>
}
TypeScript5.8
conditional type
により T
型のパターン分けがされ戻り値をNarrowingできる。
5.8以前は Success<T['data']>
でのインデックスアクセスができなかったのでこれができるようになっている
type Success<T> = { data: T, isResult: 'Success' }
type Failure = { isResult: 'Failure' }
type ObjectValues = Record<'data', unknown> | Record<'error', unknown>
const maybeHasData = <T extends ObjectValues>(value: T):
T extends Record<'data', unknown>
? Success<T['data']>:
T extends Record<'error', unknown>
? Failure : never => {
if ('data' in value) {
return { ...value, isResult: 'Success' }
}
return { isResult: 'Failure' }
}
const result1 = maybeHasData({ data: 'foo' }) // Success<{data: string;}>
const result2 = maybeHasData({ error: 'a' }) // Failure

TypeScript5.8以前で同様のことをやりたいと思っても型解決できない
Type 'T & { isResult: "Success"; data: unknown; }' is not assignable to type 'T extends Record<"data", unknown> ? Success<T["data"]> : T extends Record<"error", unknown> ? Failure : never'.(2322)
このスクラップは2025/02/07にクローズされました