
View on GitHub: https://tsch.js.org/4
T에서 K 프로퍼티만 선택해 새로운 오브젝트 타입을 만드는 내장 제네릭 Pick<T, K>을 사용하지 않고 구현하세요.
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };
T는 원본 타입K는 T의 프로퍼티 키 타입 (extends keyof T를 활용해 T의 프로퍼티 키 타입으로 제한)[P in K]는 K의 각 프로퍼티 키를 순회하며 새로운 타입을 생성T[P]는 P 프로퍼티 키(key)의 값(value)을 가져옴
as와extends차이
as: 타입 단언 or 매핑된 타입 변환extends: 타입 제약(generic) or 조건부 타입(conditional type) 정의// as의 사용(1): 타입 단언
const value: unknown = "hello";
const length = (value as string).length; // 타입 단언
// as의 사용(2): 매핑된 타입 변환
type RenameKeys<T> = {
[K in keyof T as `new_${string & K}`]: T[K];
};
type Original = { id: number; name: string };
type Renamed = RenameKeys<Original>;
// 결과:
// {
// new_id: number;
// new_name: string;
// }
// extends의 사용(1): 타입 제약
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
// extends의 사용(2): 조건부 타입 정의
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
[P in K]란 무엇인가?
[]는 매핑된 타입에서 특정 키를 순회하며 새로운 타입을 생성할 때 사용(index 아님)
P는 매핑된 키를 나타내는 변수
in은 순회(iteration)를 나타내는 키워드로, K의 각 요소를 순회
K는 순회할 키의 집합(K는 일반적으로 keyof T처럼 타입의 키 집합)
[P in K]는 K에 포함된 키를 하나씩 순회하며 새로운 타입의 키를 정의
type MappedType = {
[P in K]: ValueType; // 매핑된 타입의 키와 값 정의
};
View on GitHub: https://tsch.js.org/7
T에서 모든 프로퍼티를 읽기 전용으로 만드는 내장 제네릭 Readonly<T>을 사용하지 않고 구현하세요.
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
};
[P in keyof T]: T의 모든 프로퍼티 키를 순회하며 새로운 타입을 생성readonly: 프로퍼티를 읽기 전용으로 만듦T[P]는 P 프로퍼티 키(key)의 값(value)을 가져옴'readonly' 키워드는 무엇인가?
Typescript 고유의 Type Modifier// 객체 타입의 프로퍼티
interface User {
readonly id: number;
name: string;
}
const user: User = { id: 1, name: "Hayou" };
user.id = 2; // 오류: 'id'는 읽기 전용 속성입니다.
// 배열
const numbers: readonly number[] = [1, 2, 3];
numbers[0] = 4; // 오류: 읽기 전용 배열에서는 값을 변경할 수 없습니다.
numbers.push(4); // 오류: 읽기 전용 배열에서는 요소를 추가할 수 없습니다.
// 매핑된 타입
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
};
interface User {
id: number;
name: string;
}
type ReadonlyUser = MyReadonly<User>;
const user: ReadonlyUser = { id: 1, name: "Hayou" };
user.id = 2; // 오류: 'id'는 읽기 전용 속성입니다.
View on GitHub: https://tsch.js.org/11
배열(튜플)을 받아, 각 원소의 값을 key/value로 갖는 오브젝트 타입을 반환하는 타입을 구현하세요.
type TupleToObject<T extends readonly any[]> = { [P in T[number]]: P };
T는 배열(튜플) 타입T[number]는 배열 T의 모든 요소 타입을 나타냄 (배열 T의 인덱스에 있는 모든 타입을 집합으로 반환)[P in T[number]]는 T[number]의 각 원소를 순회하며 새로운 타입을 생성
[P in T]가 안되는 이유
T는 ['tesla', 'model 3', 'model X']라는 배열의 "전체"를 가리킴type T = ["tesla", "model 3", "model X"];
매핑된 타입에서 키는 배열 전체가 될 수 없고, 반드시 키로 사용할 수 있는 타입이어야 함
반면, T[number]는 배열 T의 요소 타입만을 추출하여 배열의 모든 요소를 하나의 집합으로 표현
배열 T의 각 요소가 P로 순회될 수 있도록 만들어 줌
type T = ["tesla", "model 3", "model X"];
type TElement = T[number]; // 'tesla' | 'model 3' | 'model X'
View on GitHub: https://tsch.js.org/14
배열(튜플) T를 받아 첫 원소의 타입을 반환하는 제네릭 First<T>를 구현하세요.
type First<T extends any[]> = T extends [] ? never : T[0];
T extends []는 배열 T가 비어있는지 확인T[0]는 배열 T의 첫 번째 요소를 가져옴T extends [] ? never : T[0]는 배열 T가 비어있으면 never를 반환하고, 비어있지 않으면 첫 번째 요소를 반환View on GitHub: https://tsch.js.org/18
배열(튜플)을 받아 길이를 반환하는 제네릭 Length<T>를 구현하세요.
type Length<T extends readonly any[]> = T["length"];
T extends readonly any[]는 튜플 T가 읽기 전용 배열이라는 것을 확인T["length"]는 튜플 T의 길이를 반환왜 읽기 전용 배열이어야 하는가?
type Length<T extends any[]> = T["length"]; // readonly 제거
const tesla = ["tesla", "model 3", "model X", "model Y"]; // as const 제거
Expect<Equal<Length<typeof tesla>, 4>>와 Expect<Equal<Length<typeof spaceX>, 5>>가 false가 된다.const tesla = ['tesla', 'model 3', 'model X', 'model Y'])은 기본적으로 수정 가능한 배열(string[])로 간주됩니다. 즉, typeof tesla의 타입은 string[]이다.type TeslaType = string[]; // 배열의 요소 타입은 string, 길이는 고정되지 않음
type TeslaTypeAsConst = readonly ["tesla", "model 3", "model X", "model Y"]; // 배열의 요소 타입은 string, 길이는 4
Length<T>는 배열 타입에서 length 프로퍼티를 참조한다. 하지만 배열이 단순히 string[]로 추론되면, 배열의 길이에 대한 정보를 포함하지 않음.Length<typeof tesla>는 정확히 4라는 값 타입이 아니라, number 타입으로 추론됨View on GitHub: https://tsch.js.org/43
T에서 U에 할당할 수 있는 타입을 제외하는 내장 제네릭 Exclude<T, U>를 이를 사용하지 않고 구현하세요.
type MyExclude<T, U> = T extends U ? never : T;
T extends U는 T가 U에 할당할 수 있는지(T가 U의 서브타입인지) 여부를 확인T가 U에 할당할 수 있으면 never를 반환하고, 그렇지 않으면 T를 반환유니온 타입('a' | 'b' | 'c')에서
T가 동작하는 방식
T는 유니온 타입의 각 구성 요소에 대해 개별적으로 판단 (이 예시에서는 extends를 판단)