2024.10.27
boolean
또는 리터럴 타입)하거나 무한(number
또는 string
)합니다.타입스크립트 용어 | 집합 용어 |
---|---|
never | ∅ (공집합) |
리터럴 타입 | 원소가 1개인 집합 |
값이 T에 할당 가능 | 값 ∈ T (값이 T의 원소) |
T1이 T2에 할당 가능 | T1 ⊆ T2 (T1이 T2의 부분 집합) |
T1이 T2를 상속 | T1 ⊆ T2 (T1이 T2의 부분 집합) |
T1 | T2 (T1과 T2의 유니온) |
T1 & T2 (T1과 T2의 인터섹션) | T1 ∩ T2 (T1과 T2의 교집합) |
unknown | 전체 (universal) 집합 |
interface Person {
name: string;
age: number;
}
const employee: Person = {
name: '홍길동',
age: 30,
department: '개발팀', // 추가적인 속성
};
interface A {
name: string;
}
interface B {
age: number;
}
type C = A & B;
const person: C = {
name: '홍길동',
age: 30,
};
// Person 인터페이스 정의
interface Person {
name: string;
}
// PersonSpan 인터페이스는 Person을 상속 (서브타입 관계)
interface PersonSpan extends Person {
birth: Date;
death?: Date;
}
// Person은 PersonSpan의 상위 타입
// PersonSpan은 Person의 서브타입이며, Person에 할당 가능 (부분집합 관계)
// Person 타입의 변수
let person: Person;
// PersonSpan 타입의 객체
const personSpan: PersonSpan = {
name: 'John Doe',
birth: new Date('1980-01-01'),
death: new Date('2020-01-01'),
};
// PersonSpan은 Person의 서브타입이므로 personSpan을 person에 할당 가능
person = personSpan; // 상속(extends), 서브타입(subtype), 할당 가능(assignable)
console.log(person.name); // person.name을 접근할 수 있음 (Person의 속성)
type
과 interface
같은 키워드는 타입 공간에만 존재합니다.class
나 enum
같은 키워드는 타입과 값 두 가지로 사용될 수 있습니다."foo"
는 문자열 리터럴이거나, 문자열 리터럴 타입일 수 있습니다. 차이점을 알고 구별하는 방법을 터득해야 합니다.typeof
, this
그리고 많은 다른 연산자들과 키워드들은 타입 공간과 값 공간에서 다른 목적으로 사용될 수 있습니다.// 타입 공간에서의 typeof
type T1 = typeof p; // 타입은 Person
type T2 = typeof email; // 타입은 (p: Person, subject: string, body: string) => Response
// 값 공간에서의 typeof
const v1 = typeof p; // 값은 "object"
const v2 = typeof email; // 값은 "function"
as Type
)보다 타입 선언(: Type
)을 사용해야 합니다.const elNull = document.getElementByld('foo'); // 타입은 HTMLElement | null
const el = document.getElementByld('foo')!; // 타입은 HTMLElement
String
대신 string
, Number
대신 number
, Boolean
대신 boolean
, Symbol
대신 symbol
, BigInt
대신 bigint
를 사용해야 합니다.function isGreeting(phrase: string) {
return ['hello', 'good day'].includes(phrase);
}
// ~~~~~
// 'String' 형식의 인수는
// 'string' 형식의 매개변수에 할당될 수 없습니다.
// 'string'은 기본 개체이지만 'String'은 래퍼 개체입니다.
// 가능한 경우 'string'을 사용하세요.
interface Room {
numDoors: number;
ceilingHeightFt: number;
}
const r: Room = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present',
// ~~~~~~~~~~~~~~~~ 객체 리터럴은 알려진 속성만 지정할 수 있으며 'Room' 형식에 'elephant'이(가) 없습니다.
};
const obj = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present',
};
const r: Room = obj; // 정상
// obj의 타입은 { numDoors: number; ceilingHeightFt: number; elephant: string }으로 추론됩니다.
// obj 타입은 Room 타입의 부분 집합을 포함하므로, Room에 할당 가능하며 타입 체크도 통과합니다
interface Room {
numDoors: number;
ceilingHeightFt: number;
}
// 잉여 속성 체크 발생 (오류)
const r1: Room = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present', // 오류: 'Room' 타입에 'elephant' 속성이 존재하지 않습니다.
};
// 임시 변수를 사용하면 잉여 속성 체크를 건너뜀 (정상)
const obj = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present',
};
const r2: Room = obj; // 정상: obj는 'Room' 타입과 호환 가능
typeof fn
을 사용하면 됩니다.type
과 interface
두 가지 문법을 사용해서 작성하는 방법을 터득해야 합니다.extends
키워드로 인터페이스 확장.&
를 사용하여 여러 타입을 하나로 결합.Partial
, Readonly
등을 사용하여 기존 타입 변형.extends
를 사용해서 인터페이스 필드의 반복을 피해야 합니다.keyof
, typeof
, 인덱싱, 매핑된 타입들이 포함됩니다.extends
를 사용하면 됩니다.Pick
, Partial
, ReturnType
같은 제너릭 타입에 익숙해져야 합니다.undefined
를 추가하는 것을 고려해야 합니다.Record
, 매핑된 타입 같은 인덱스 시그니처보다 정확한 타입을 사용하는 것이 좋습니다.number
타입은 버그를 잡기 위한 순수 타입스크립트 코드입니다.number
를 사용하기보다 Array
나 튜플, 또는 ArrayLike
타입을 사용하는 것이 좋습니다.readonly
로 선언하는 것이 좋습니다. readonly
매개변수는 인터페이스를 명확하게 하며, 매개변수가 변경 되는 것을 방지합니다.readonly
를 사용하면 변경하면서 발생하는 오류를 방지할 수 있고, 변경이 발생하는 코드도 쉽게 찾을 수 있습니다.const
와 readonly
의 차이를 이해해야 합니다. readonly
는 얕게 동작한다는 것을 명심해야 합니다.const REQUIRES_UPDATE: { [k in keyof ScatterProps]: boolean } = {
xs: true,
ys: true,
xRange: true,
yRange: true,
color: true,
onClick: false,
};
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
let k: keyof ScatterProps;
for (k in oldProps) {
if (oldProps[k] !== newProps[k] && REQUIRES_UPDATE[k]) {
return true;
}
}
return false;
}