[230624] Typescript 공식문서 & 문제풀기
1. Typescript Indexed Access Types 정독 및 정리 완료
- 인덱스 접근 타입(indexed acces type) 을 사용하여 특정 속성을 추출할 수 있음
- 인덱스 접근 타입은
[ ]
대괄호를 사용 - 위 예시는 Age 는 Person 타입의 age 속성의 타입인 number가 됨
- 인덱싱 타입은 유니온, keyof 또는 다른 타입들과 함께 사용 가능 → 인덱싱 타입 자체가 타입이기 때문 (속성의 타입을 가져오는 기능을 제공하는 타입)
// @errors: 2538 2749
type Person = { age: number; name: string; alive: boolean };
// ---cut---
const key = "age";
type Age = Person[key];
===> 불가능
type Person = { age: number; name: string; alive: boolean };
// ---cut---
type key = "age";
type Age = Person[key];
===> 가능
- const (상수)를 사용하여 타입으로 인덱싱할 수 없다.
- 하지만
type
타입별칭을 사용해서 할 수는 있다.
유니온 예시
type Person = { age: number; name: string; alive: boolean };
// ---cut---
type I1 = Person["age" | "name"];
// I1 = string | number
type I2 = Person[keyof Person];
// string | number | boolean
type AliveOrName = "alive" | "name";
type I3 = Person[AliveOrName];
// boolean | string
존재하지 않는 프로퍼티를 인덱싱하면 오류 발생
typeof 와 결합해서 편리하게 타입 가져오기
const MyArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
type Person = (typeof MyArray)[number];
// 타입 Person은 { name: string; age: number; }입니다.
type Age = (typeof MyArray)[number]["age"];
// 타입 Age는 number입니다.
2. Conditional Types 정독 및 정리 완료
- 조건부 타입 extends 랑 비슷함
- 제너릭이랑도 함께 쓰면 유용하다.
- 자세한건 노션 참고
- Documentation - Conditional Types
조건부 타입
- 조건부 타입은 (
condition ? trueExpression : falseExpression
) js 조건 표현식과 비슷한 형식을 가짐 - extends 의 왼쪽에 있는 타입이 오른쪽에 있는 타입에 할당 가능한 경우 첫번째 분기 반환
- 그렇지 않은 경우 두번째 분기 반환
조건부 타입 제네릭과 함께 응용 방법
// number 이면 IdLabel , 아니면 NameLabel
type NameOrId<T extends number | string> = T extends number
? IdLabel
: NameLabel;
function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
throw "unimplemented";
}
let a = createLabel("typescript");
// let a: NameLabel
let b = createLabel(2.8);
// let b: IdLabel
let c = createLabel(Math.random() ? "hello" : 42);
//let c: NameLabel | IdLabel
조건부 타입으로 제한하기
// 위와 같이 message 를 속성으로 사용하고 있냐 없냐 제한을 둘 수 있음
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;
interface Email {
message: string;
}
interface Dog {
bark(): void;
}
type EmailMessageContents = MessageOf<Email>;
//type EmailMessageContents = string
type DogMessageContents = MessageOf<Dog>;
//type DogMessageContents = never
조건부 타입 내에서 추론하기
- infer 타입 시스템에서 미리 정의된 키워드
- infer 키워드를 쓰면 조건부 타입에서 제너릭처럼 사용할 수 있음 (타입을 추론함)
- true 분기에서 사용 가능
- infer 는 조건부 extends 절에서만 사용이 가능하다
T extends infer U ? X : Y
- 위에가 기본 구조인데 U가 타입 추론이 가능하면 타입이 X가 들어간다.
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;
분배적 조건부 타입
- 조건부 타입이 제네릭 타입을 다룰 때, 유니온 타입으로 주어지면 분배적이 됨
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>;
// type StrArrOrNumArr = string[] | number[]
- 분배적 조건부 타입은 유용할때도 많지만 때로는 예상치 못한 결과를 초례함
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>;
// type StrArrOrNumArr = string[] | number[]
-
위와 같이 넣으면 (string number) [] 가 아니라 string[] number[] 임
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
// 'StrArrOrNumArr' is no longer a union.
type StrArrOrNumArr = ToArrayNonDist<string | number>;
// (string | number) []
-
방지하려면 양 옆에 괄호를 넣어주면 (string number) [] 타입이 된다.
Leave a comment