banner
 Sayyiku

Sayyiku

Chaos is a ladder
telegram
twitter

TypeScript マッピング型

読み取り専用型 Readonly#

定義:T 型のすべてのプロパティを読み取り専用状態に設定します。

type Readonly<T> = {
  readonly [P in keyof T]: T[P]
}

用法:

interface Person {
  name: string
  age: number
}

const person: Readonly<Person> = {
  name: 'Lucy',
  age: 22,
}

// エラー:Cannot assign to 'name' because it is a read-only property
person.name = 'Lily'

readonly 読み取り専用、 readonly マークされたプロパティは宣言時またはクラスのコンストラクタ内でのみ値を設定でき、その後は変更不可(つまり読み取り専用プロパティ)。

読み取り専用配列 ReadonlyArray#

定義:T 型の配列を読み取り専用状態に設定します。配列の初期化時にのみ変数に値を設定でき、その後配列は変更できません。

interface ReadonlyArray<T> {
  [Symbol.iterator](): IterableIterator<T>
  entries(): IterableIterator<[number, T]>
  keys(): IterableIterator<number>
  values(): IterableIterator<T>
}

用法:

interface Person {
  name: string
}

const personList: ReadonlyArray<Person> = [{ name: 'Jack' }, { name: 'Rose' }]

// エラー:Property 'push' does not exist on type 'readonly Person[]'
// personList.push({ name: 'Lucy' })

// しかし、内部要素が参照型の場合、要素自体は変更可能です
personList[0].name = 'Lily'

オプショナル型 Partial#

定義:T 型のすべてのプロパティをオプショナル状態に設定します。まず keyof T を使用して型 T のすべてのプロパティを取得し、次に in 演算子でループし、最後にプロパティの後に ? を追加してプロパティをオプショナルプロパティにします。

type Partial<T> = {
  [P in keyof T]?: T[P]
}

用法:

interface Organization {
  id: number
  name: string
  address: string
  type: string
  nationality: string
}

const params: Partial<Organization> = {
  address: '...new address',
}

// 上記の Partial と同じ効果
const params: Pick<Organization, 'address'> = {
  address: '...new address',
}

必須型 Required#

定義:Partial<T> の作用とは逆に、T 型のすべてのプロパティを必須状態に設定します。まず keyof T を使用して型 T のすべてのプロパティを取得し、次に in 演算子でループし、最後にプロパティの後の ? の前に - を追加してプロパティを必須プロパティにします。

type Required<T> = {
  [P in keyof T]-?: T[P]
}

用法:

interface Person {
  name?: string
  age?: number
}

// Required マッピング後に返される新しい型では、name と age はどちらも必須プロパティになります
// エラー:Type '{}' is missing the following properties from type 'Required<Person>': name, age
let person: Required<Person> = {}

プロパティ抽出 Pick#

定義:T 型から一部のプロパティを抽出し、新しい返り値型として使用します。

type Pick<T, K extends keyof T> = {
  [P in K]: T[P]
}

用法:

interface Goods {
  type: string
  goodsName: string
  price: number
}

// type RequestGoodsParams = {
//     goodsName: string;
//     price: number;
// }
type RequestGoodsParams = Pick<Goods, 'goodsName' | 'price'>

const params: RequestGoodsParams = {
  goodsName: '',
  price: 10,
}

プロパティ除外 Omit#

定義:Pick の作用とは逆に、T 型から一部のプロパティを除外し、新しい型を返します。

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

用法:

interface Rectangular {
  length: number
  height: number
  width: number
}

// type Square = {
//     length: number;
// }
type Square = Omit<Rectangular, 'height' | 'width'>

Omit 推導プロセス:

type Person = {
  name: string
  age: string
  location: string
}

type PersonWithoutLocation = Omit<Person, 'location'>
// 推導
type PersonWithoutLocation = Pick<Person, Exclude<'name' | 'age' | 'location', 'location'>>
// 推導
type PersonWithoutLocation = Pick<
  Person,
  ('name' extends 'location' ? never : 'name') | ('age' extends 'location' ? never : 'age') | ('location' extends 'location' ? never : 'location')
>
// 推導
type PersonWithoutLocation = Pick<Person, 'name' | 'age' | never>
// 推導
type PersonWithoutLocation = Pick<Person, 'name' | 'age'>
// 推導
type PersonWithoutLocation = {
  [p in 'name' | 'age']: Person[p]
}
// 推導
type PersonWithoutLocation = {
  name: string
  age: string
}

抽出型 Extract<T,U>#

定義:T の中から U に代入可能な型を抽出します。

type Extract<T, U> = T extends U ? T : never

用法:

type T01 = Extract<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'> // 'a' | 'c'

type T02 = Extract<string | number | (() => void), Function> // () => void

除外型 Exclude<T,U>#

定義:Extract の用法とは逆に、T から U に代入可能な型を除外します。

type Exclude<T, U> = T extends U ? never : T

用法:

type T00 = Exclude<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'> // 'b' | 'd'

type T01 = Exclude<string | number | (() => void), Function> // string | number

プロパティマッピング Record<K,T>#

定義:2 つのジェネリックを受け取ります。Kstring | number | symbol に代入可能な型でなければなりません。in 演算子を使用して K をループし、各プロパティの型は T 型でなければなりません。

type Record<K extends string | number | symbol, T> = {
  [P in K]: T
}

Record は TypeScript の中で非常に便利なジェネリック型です。2 つの具体的なパラメータ型 Record<K, V> を必要とし、オブジェクトの型を指定するために使用されます。オブジェクトのすべてのキーは K 型であり、これらのキーに対応する値はすべて V 型です。Record 型を使用しない場合、同等の効果を得るためには次のような方法が必要です:

type RecordExample = Record<string, number>

// 等価
interface EquivalentExample {
  [key: string]: number
}

用法 1:Person 型の配列をオブジェクトマッピングに変換:

interface Person {
  name: string
  age: number
}

const personList = [
  { name: 'Jack', age: 26 },
  { name: 'Lucy', age: 22 },
  { name: 'Rose', age: 18 },
]

const personMap: Record<string, Person> = {}

personList.forEach((person) => {
  personMap[person.name] = person
})

用法 2:パラメータを渡すとき、パラメータがオブジェクトであることを望むが、具体的な型が不明な場合、Record をパラメータ型として使用できます:

function doSomething(obj: Record<string, any>) {}

用法 3:関数を書いて、パラメータオブジェクトのすべての値を対応する数字に変換し、入力と出力のオブジェクトが同じキーを持つことを保証します:

type Input = Record<string, string>
function transform<T extends Input>(input: T): Record<keyof T, number> {
  const keys: (keyof T)[] = Object.keys(input)
  return keys.reduce((acc, key) => {
    acc[key] = +input[key]
    return acc
  }, {} as Record<keyof T, number>)
}

ただし、ユニオン型を使用する場合、Record 自体にも制限があります(これは TypeScript の制限です)。上記の 'apple' | 'banana' | 'orange' の例を考えると、次のように書くと、以下のコードはエラーになります:

type Fruit = 'apple' | 'banana' | 'orange'
type Price = Record<Fruit, number>
// 型エラー
const prices: Price = {
  apple: 20,
}

Record は自然にオプショナルキーの状況を解決できません。Record<'A' | 'B', number> の意味は A と B がこの型のキーである必要があるということであり、A または B のいずれかだけがキーであればよいということではありません。このようなオプショナルな状況には、再度 Partial を使用してニーズを満たすことができます:

type Price = Partial<Record<Fruit, number>>
// 正しい
const prices: Price = {
  apple: 20,
}

非ヌル型 NonNullable#

定義:T から nullundefinednever 型を除外しますが、voidunknown 型は除外しません。

type NonNullable<T> = T extends null | undefined ? never : T

用法:

type T01 = NonNullable<string | number | undefined> // string | number

type T02 = NonNullable<(() => string) | string[] | null | undefined> // (() => string) | string[]

type T03 = NonNullable<{ name?: string; age: number } | string[] | null | undefined> // {name?: string, age: number} | string[]

コンストラクタ引数型 ConstructorParameters#

定義:クラスのコンストラクタ引数型からなるタプル型を返します。

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never

用法:

class Person {
  name: string
  age: number
  gender: 'man' | 'women'

  constructor(name: string, age: number, gender: 'man' | 'women') {
    this.name = name
    this.age = age
    this.gender = gender
  }
}

type ConstructorType = ConstructorParameters<typeof Person> //  [name: string, age: number, gender: 'man' | 'women']

const params: ConstructorType = ['Jack', 20, 'man']

インスタンス型 InstanceType#

定義:class コンストラクタの返り値型を取得します。

type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any

用法:

class Person {
  name: string
  age: number
  gender: 'man' | 'women'

  constructor(name: string, age: number, gender: 'man' | 'women') {
    this.name = name
    this.age = age
    this.gender = gender
  }
}

type Instance = InstanceType<typeof Person> // Person

const params: Instance = {
  name: 'Jack',
  age: 20,
  gender: 'man',
}

関数引数型 Parameters#

定義:関数の引数型からなるタプル型を取得します。

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never

用法:

type FunctionType = (name: string, age: number) => boolean

type FunctionParamsType = Parameters<FunctionType> // [name: string, age: number]

const params: FunctionParamsType = ['Jack', 20]

関数戻り値型 ReturnType#

定義:関数の戻り値型を取得します。

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any

使用:

type FunctionType = (name: string, age: number) => boolean | string

type FunctionReturnType = ReturnType<FunctionType> // boolean | string
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。