✨타입 별칭 vs 인터페이스
- 인터페이스는 병합(merge)할 수 있습니다. 내장된 전역 인터페이스 혹은 외부 코드를 사용할 때 유용합니다.
- 인터페이스는 클래스가 선언된 구조의 타입을 확인하는 데 사용할 수 있지만, 타입 별칭은 그럴 수 없습니다.
- 일반적으로 인터페이스가 더 빨리 작동합니다.
✨속성 타입
선택적 속성
interface Poet{
born?: number; // ? 키워드로 선택적 속성 사용
name: string;
};
읽기 전용 속성
interface Poet{
readonly born: number;
// readonly 키워드를 이용하여 다른 값으로 설정할 수 없음을 나타냅니다.
name: string;
};
const poet: Poet = {
born: 1980,
name: "ABC"
}
poet.born = 2000 // ERROR Cannot assign to 'born' because it is a read-only property.
함수와 메서드
interface HasBothFunctionTypes {
property: () => string;
property2: () => string;
method(): string;
}
const hasBoth: HasBothFunctionTypes = {
property(){
return ""
},
property2: () => "",
method(){
return ""
},
}
- 메서드는 readonly로 선언할 수 없지만, 속성은 가능합니다.
- 인터페이스의 병합과 일부 작업은 메서드와 속성을 다르게 처리합니다.
- 기본 함수가 this를 참조할 수 있다는 것을 알고 있다면 메서드를 사용하세요.
- 반대의 경우 속성 함수를 사용하세요.
호출 시그니처
호출 시그니처란 값을 함수처럼 호출하는 방식에 대한 타입 시스템 설명입니다.
type FunctionAlias = (input: string) => number;
interface CallSignature {
(input: string): number; // 값을 함수처럼 호출하는 방식에 대한 타입 시스템 설명
}
const typedFunctionAlias: FunctionAlias = (input) => input.length;
const typedCallSignature: CallSignature = (input) => input.length;
호출 시그니처는 속성을 추가로 갖는 함수를 설명하는 데 사용할 수 있습니다.
interface FunctionWithCount{
count: number;
() : void;
}
let hasCallCount: FunctionWithCount;
function keepsTrackOfCalls() {
keepsTrackOfCalls.count += 1;
console.log(`called ${keepsTrackOfCalls.count} times`)
}
keepsTrackOfCalls.count = 0;
hasCallCount = keepsTrackOfCalls
인덱스 시그니처
interface WordCounts{
[i: string]: number;
}
const counts: WordCounts = {};
counts.apple = 0; // OK
counts.banana = false; // ERROR Type 'boolean' is not assignable to type 'number'.
아래와 같은 상황에서 오류를 나타내지 못합니다.
따라서 키/값 쌍을 저장하는데 키 값을 미리 알 수 없다면, Map을 사용하는 편이 안전합니다.
interface DatesByName {
[i: string]: Date;
}
const publishDates: DatesByName = {
Frankenstein: new Date("1 January 1818")
}
publishDates.Frankenstein // Date 타입
console.log(publishDates.Frankenstein.toString())
publishDates.Abc // Date 타입 그러나 실제 값은 undefined.
console.log(publishDates.Abc.toString()) // 타입 오류는 나지 않지만 ERROR 발생
1️⃣ 속성과 인덱스 시그니처 혼합
명명된 속성에 대해 구체적인 속성 타입 리터럴을 사용할 수 있습니다.
interface HisToricalNovels {
Oroonoko: 1688;
[i: string]: number;
}
const novels: HisToricalNovels = {
Oroonoko: 1688,
Outlander: 1991,
}
const novels: HisToricalNovels = {
Oroonoko: 1688,
Outlander: 1991,
}
const notSameYear: HisToricalNovels = {
Oroonoko: 1689, //ERROR Type '1689' is not assignable to type '1688'.
Outlander: 1991,
}
const missingOrronoko: HisToricalNovels = {
Outlander: 1991,
}
/* ERROR
Property 'Oroonoko' is missing in type '{ Outlander: number; }'
but required in type 'HisToricalNovels'.*/
2️⃣숫자 인덱스 시그니처
숫제 인덱스 시그니처를 사용할 땐 다음과 같은 주의사항이 있다.
interface MoreNarrowNumbers {
[i: number]: string;
[i: string]: string | undefined
}
interface MoreNarrowStrings {
[i: string]: string;
[i: number]: string | undefined
/*ERROR
'number' index type 'string | undefined' is not assignable
to 'string' index type 'string'.
*/
}
✨ 인터페이스의 확장
타입스크립트는 다른 인터페이스의 멤버를 복사하여 선언할 수 있는 확장(extend) 기능을 허용합니다.
interface Writing {
title: string;
}
interface Novel extends Writing {
pages: number
}
const novel: Novel = {
title: "ABC",
pages: 123
}
재정의된 속성
파생 인터페이스는 기존 인터페이스의 속성을 재정의 하거나 대체할 수 있습니다.
interface Novel {
title: string | null;
pages: number
}
interface NewNovel extends Novel {
title: string
}
const novel: NewNovel = {
title: null, // ERROR Type 'null' is not assignable to type 'string'
pages: 123
}
다중 인터페이스 확장
interface GivesNumber {
giveNumber() : number;
}
interface GivesString {
giveString() : string;
}
interface GivesBothAndEither extends GivesNumber, GivesString {
giveBothAndEither() : string | number;
}
✨ 인터페이스 병합
동일한 이름, 동일한 스코프에 선언된 경우 병합됩니다.
interface Merged {
first: string;
}
interface Merged {
second: string;
}
const obj: Merged = {
first: "A",
second: "B"
}
1️⃣ 병합이 사용되는 경우?
일반적으로 병합은 혼란을 야기하기 때문에 자주 사용되지 않습니다.
하지만 외부 패키지나 Window 같은 내장 전역 인터페이스를 보강하는데 특히 유용합니다.
interface Window {
myEnvironmentVariable: string;
}
이름이 충돌되는 멤버
나중에 병합된 인터페이스에도 동일한 타입이 사용되어야 합니다.
interface Merge {
same: (input: boolean) => string;
different: (input: string) => string;
}
interface Merge {
same: (input: boolean) => string; // OK
different: (input: boolean) => string; //ERROR
/* Subsequent property declarations must have the same type.
Property 'different' must be of type '(input: string) => string',
but here has type '(input: boolean) => string'. */
}
'기술 서적 > 하루 30분 러닝 타입스크립트' 카테고리의 다른 글
[하루 30분 러닝 타입스크립트] 클래스(2) (0) | 2024.01.08 |
---|---|
[하루 30분 러닝 타입스크립트] 클래스(1) (0) | 2024.01.07 |
[하루 30분 러닝 타입스크립트] 배열 (0) | 2023.12.27 |
[하루 30분 러닝 타입스크립트] 함수 (0) | 2023.12.23 |
[하루 30분 러닝 타입스크립트] 객체 (0) | 2023.12.22 |