LoginSignup
5
2

More than 5 years have passed since last update.

TypeScript3.0 予習 - NightlyBuild -

Last updated at Posted at 2018-06-28

先日このPRがマージされていたので早速試してみた。
https://github.com/Microsoft/TypeScript/pull/24897

以下で NightlyBuild が試せる。

npm install typescript@next

spread expression

v2.8 から Type inference in conditional types で、推論中に n番目のキャプチャ をとることができていた。 v3.0 からは spread expression が可能になるため以下の様な Tuple n番目のキャプチャをとることが可能。

typing.ts
// v2.8 から可能になった Type inference in conditional types による
// n番目引数のキャプチャ

type A1<Func> = Func extends (a1: infer A, ...args: any[]) => any ? A : never
type A2<Func> = Func extends (a1: any, a2: infer A, ...args: any[]) => any ? A : never

// v3.0 NightlyBuild では以下の spread expression が可能

type I0<Tuple> = Tuple extends [infer A, ...any[]] ? A : never
type I1<Tuple> = Tuple extends [any, infer A, ...any[]] ? A : never

以下の通り可変長引数を Tuple として扱えることが書かれている。

Strong typing of bind, call, and apply

PR に書いてある通りで、この機能の追加 + ThisType で mixin などの推論が強力になると思われる。また、可変長引数によって処理を振り分けたりするAPIを持つライブラリに有効。雑に何かを書いてみた。(こんな節操のないコードが存在しないことを祈りたい…)

convert.js
function convert(...args) {
  if (typeof args[0] === 'string') {
    return [...args].map(arg => String(arg))
  }
  if (typeof args[1] === 'boolean') {
    return [...args].map(arg => Boolean(arg))
  }
  if (typeof args[2] === 'number') {
    return [...args].map(arg => Number(arg))
  }
  return args
}
convert.ts
type NSB = number | string | boolean

type I0<T> = T extends [infer A, ...any[]] ? A : never
type I1<T> = T extends [any, infer A, ...any[]] ? A : never
type I2<T> = T extends [any, any, infer A, ...any[]] ? A : never

type isFirstArgString<T> = I0<T> extends string ? T : never
type isSecondArgBool<T>  = I1<T> extends boolean ? T : never
type isThirdArgNumber<T> = I2<T> extends number ? T : never

type ConvertedList<T>  = T extends isFirstArgString<T> ? string[] :
                         T extends isSecondArgBool<T> ? boolean[] :
                         T extends isThirdArgNumber<T> ? number[] :
                         T

function convert<T extends NSB[]>(...args: T) {
  if (typeof args[0] === 'string') {
    return [...args].map((arg: NSB) => String(arg)) as ConvertedList<T>
  }
  if (typeof args[1] === 'boolean') {
    return [...args].map((arg: NSB) => Boolean(arg)) as ConvertedList<T>
  }
  if (typeof args[2] === 'number') {
    return [...args].map((arg: NSB) => Number(arg)) as ConvertedList<T>
  }
  return args as ConvertedList<T>
}
const T1 = convert('0', true, 2) // T1: string[] = ["0", "true", "2"]
const T2 = convert(0, true, 2)   // T2: boolean[] = [false, true, true]]
const T3 = convert(0, '1', 2)    // T3: number[] = [0, 1, 2]
const T4 = convert(0, '1', '2')  // T4: [0, "1", "2"] = [0, "1", "2"]

スキーマが微妙に違うインスタンスを配列に保持している場合、抽出したインスタンスの規約を推論出来るなども考えられそう。強い。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2