[key: K]: T
와 같이 타입을 명시하면 해당 타입의 속성 키는 모두 K타입이어야 하고 속성 값은 모두 T 타입을 가져야 한다는 의미이다.interface StringNumber {
[key: string]: number;
};
const scores: StringNumber = {
Alice: 90,
Bob: 85,
Charlie: 92,
};
interface NumberArray {
[index: number]: string;
};
let myArray: NumberArray = ["Alice", "Bob", "Charlie"];
interface IndexSignatures {
[key: string]: number | boolean;
length: number;
isValid: boolean;
name: string; // 에러 발생
}
keyof
와 in
을 사용해 타입의 키들을 순회하며 각 속성에 대한 새로운 정의를 할 수 있다.type Example = {
a: number;
b: string;
c: boolean;
};
type Subset<T> = {
[K in keyof T]?: T[K];
};
const exampleSubset: Subset<Example> = { a: 3 };
P in keyof OldType
: OldType
의 모든 속성 이름을 하나씩 가져온다.NewTypeForP
: 각 속성의 타입을 지정하거나 변형한다.type NewType = {
[P in keyof OldType]: NewTypeForP;
};
type ReadOnly<T> = {
readonly [P in keyof T]: T[P];
};
type ReadOnlyExample<T> = {
-readonly [P in keyof T]: T[P];
};
type Optional<T> = {
[P in keyof T]?: T[P];
};
type OptionalExample<T> = {
[P in keyof T]-?: T[P];
};
Partial<T>
직접 구현TypeScript에서 제공하는 Partial<T>
는 기존 객체 타입의 모든 속성을 선택적(optional)으로 만드는 제네릭 타입이다.
type MyPartial<T> = {
[P in keyof T]?: T[P];
};
Required<T>
직접 구현Required<T>
는 객체 타입의 모든 속성을 필수적(required)으로 만드는 제네릭 타입이다.
type MyRequired<T> = {
[P in keyof T]-?: T[P]
};
Readonly<T>
직접 구현Readonly<T>는
객체 타입의 모든 속성을 읽기 전용(readonly)으로 만드는 제네릭 타입이다.
type Readonly<T> = {
readonly [P in keyof T]: T[P]
};
Pick<T, K>
는 주어진 타입 T에서 속성 K만을 선택한 새로운 타입을 만드는 제네릭 타입이다.
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Person {
name: string;
age: number;
city: string;
};
type PickPerson = MyPick<Person, 'name' | 'city'>; // 'name'과 'city'만을 선택
extends
는 TypeScript에서 제약 조건을 설정할 때 사용된다. K extends keyof T
는 타입 K가 반드시 T의 속성 키들 중 하나여야 한다는 조건을 설정하는 것이다.keyof
keyof
는 타입의 모든 키를 추출하는 데 사용되며 타입의 속성 이름들을 유니언 타입으로 가져오는 역할을 한다.type Person = {
name: string;
age: number;
};
type PersonKeys = keyof Person; // 'name' | 'age'
typeof
typeof
는 JavaScript나 TypeScript에서 값의 타입을 추론하는 데 사용되며 기본적으로는 값의 타입을 가져오는 역할을 한다.const myObject = {
name: "Alice",
age: 30
};
type MyObjectType = typeof myObject;
keyof
typeof
의 결합keyof
typeof
를 함께 사용하면 객체의 타입을 먼저 추론한 다음 그 타입의 속성 키들을 가져오는 방법이다.const person = {
name: "Alice",
age: 30,
job: "Engineer"
};
type PersonKeys = keyof typeof person;
in
in keyof
type Person = {
name: string;
age: number;
};
// 맵핑된 타입을 사용해 Person의 모든 속성을 optional로 만들기
type PartialPerson = {
[P in keyof Person]?: Person[P];
};
type State = 'on' | 'off';
type StateName = `${State}-swich`; // 'on-swich' | 'off-swich'
T(Type)
, E(Element)
, K(Key)
, V(Value)
등 한 글자로 된 이름을 많이 사용한다.function identity<T>(arg: T): T {
return arg;
};
identity<string>("Hello"); // "Hello"가 반환되고 T는 string이 된다.
identity<number>(42); // 42가 반환되고 T는 number가 된다.
identity("Hello"); // TypeScript가 T를 string으로 추론한다.
identity(42); // TypeScript가 T를 number로 추론한다.
extends
키워드를 사용해 제네릭 타입에 제약을 추가할 수 있다.function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
};
getLength("Hello"); // 정상, string은 length 속성을 가짐
getLength([1, 2, 3]); // 정상, 배열은 length 속성을 가짐
getLength({ length: 10 }); // 정상, 객체에 length 속성이 있음
getLength(42); // 에러, number에는 length 속성이 없음
T extends { length: number }
는 T
는 반드시 length
속성을 가져야 한다는 제약을 의미한다.function identityWithDefault<T = string>(arg: T): T {
return arg;
};
let defaultString = identityWithDefault(10); // T는 number로 추론됨
let defaultIdentity = identityWithDefault("Hello"); // T는 string (기본값)