Closed4

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

hanzzoohanzzoo

この制限に合致されている必要があるとのこと。

function f<T extends A | B>(x: T):
    T extends A ? string :
    T extends B ? number :
    never
hanzzoohanzzoo

例えば 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
hanzzoohanzzoo

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にクローズされました