Post

타입스크립트 - 커스텀타입

IsNever

never인지 판단하는 타입

1
type IsNever<T> = [T] extends [never] ? true : false;

IsAny

any타입인지 판단하는 타입

1
type IsAny<T> = string extends number & T ? true : false;
  • number & T => any
  • string extends any

IsArray

배열인지 판단하는 타입

1
2
3
4
5
6
7
type IsArray<T> = IsNever<T> extends true
  ? false
  : T extends readonly unknown[]
  ? IsAny<T> extends true
    ? true
    : false
  : false;
  • IsArray이 never을 되는 것을 막기 위해 `IsNever extends true` 필요
  • IsArray가 boolean이 되는 것을 막기 위해 `IsAny extends true` 필요
  • IsArray<readonly []>가 false가 되는 것을 막기 위해 T extends readonly unknown[] 필요

IsTuple

배열 중에서 튜플만 판단하는 타입

1
2
3
4
5
6
7
type IsTuple<T> = IsNever<T> extends true
  ? false
  : T extends readonly unknown[]
  ? number extends T["length"]
    ? false
    : true
  : false;
  • 배열과 튜플의 가장 큰 차이점?
    • 튜플은 길이가 고정되어 있음
    • 튜플이 아닌 배열은 length가 number
    • 튜플은 1,2,3과 같은 개별 숫자
      => number extends T["length"] = false

IsUnion

유니언인지 판단하는 타입

1
2
3
4
5
6
7
type IsUnion<T, U = T> = IsNever<T> extends true
  ? false
  : T extends T
  ? [U] extends [T]
    ? false
    : true
  : false;

분배 법칙을 만들기 위해 T extends T === true, U = T 코드를 작성함

T가 string | number인 경우
T extends T는
(string extends string | number) | (number extends string | number)
[U] extends [T]는
([string | number] extends [string]) | ([string | number] extends [number])

U = T를 통해 U에 분배법칙이 일어나지 않은 원본 타입을 담아둠

[U] extends [T]는 최종적으로 IsUnion<string | number> = true가 됨

T가 string이었다면 [U] extends [T] 에서
[string] extends [string]이 되므로 true가 됨

최종적으로 IsUnion은 false가 됨

Omit

특정 객체에서 지정한 속성을 제거하는 타입

1
type diff<A, B> = Omit<A & B, keyof B>;
1
2
3
4
5
type diff<A, B> = Omit<A & B, keyof B>;
type R1 = Diff<
  { name: string; age: number },
  { name: string; married: boolean }
>;
  • { name: string; age: number }에서 { name: string; married: boolean } 속성을 제거
  • type R1 = {age:number}

Diff

대칭 차집합 타입을 구하는 타입

  • 객체에서 대칭 차집합 구하기
1
type SymDiff<A, B> = Omit<A & B, keyof (A | B)>;
  • 유니온에서 대칭 차집합 구하기
1
type SymDiff<A, B> = Omit<A | B, A & B>;

객체 대칭 차집합 예시

1
2
3
4
5
type SymDiff<A, B> = Omit<A & B, keyof (A | B)>;
type R2 = SymDiff<
  { name: string; age: number },
  { name: string; married: boolean }
>;
  • type R2 = {age:number, married:boolean}

유니온 대칭 차집합 예시

1
2
type SymDiffUnion<A, B> = Omit<A | B, A & B>;
type R3 = SymDiffUnion<1 | 2 | 3, 2 | 3 | 4>;
  • type R3 = 1 | 4

Exclude

어떤 타입에서 다른 타입을 제거하는 타입

1
type IsSubset<A, B> = A extends B ? true : false;

예시

1
2
3
type R1 = IsSubset<string, string | number>;
type R2 = IsSubset<{ name: string; age: number }, { name: string }>;
type R3 = IsSubset<symbol, unknown>;

어떠한 타입에서 지정한 타입을 제거하는 타입

1
type MyExclude<T, U> = T extends U ? never : T;
1
2
type MyExclude<T, U> = T extends U ? never : T;
type Result = MyExclude<1 | "2" | 3, string>;
  • string 타입을 제거
  • type Result = 1 | 3

어떠한 타입에서 지정한 타입만 추출하는 타입

1
type MyExtract<T, U> = T extends U ? never : T;
1
2
type MyExtract<T, U> = T extends U ? never : T;
type Result = MyExclude<1 | "2" | 3, string>;
  • string 타입만 추출
  • type Result = "2"
This post is licensed under CC BY 4.0 by the author.