첫 번째 인터페이스 (Our First Interface)
아래는 타입을 지정한 함수이다.
function printLabel(labeledObj: { label: string }) {...}
printLabel({ size: 10, label: "Size 10 Object" });
위 예제를 interface를 사용하면 아래와 같이 작성할 수 있다.
interface LabeledValue {
label: string;
}
function printLabel(labeledObj: LabeledValue) {...}
printLabel({ size: 10, label: "Size 10 Object" });
선택적 프로퍼티 (Optional Properties)
interface의 모든 프로퍼티가 필요하지 않은 상황이 있다. 특정 조건에서만 존재하거나, 아예 없을 수도 있다. 이럴 때는 아래와 같이 물음표 기호를 사용한다.
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): {color: string; area: number} {
let newSquare = {color: "white", area: 100};
if (config.color) newSquare.color = config.color;
if (config.width) newSquare.area = config.width * config.width;
return newSquare;
}
createSquare({ color: "black" });
읽기전용 프로퍼티 (Readonly Properties)
일부 프로퍼티는 처음 생성될 때만 수정 가능하고, 이후에는 수정할 수 없어야 한다. 해당 상황에서는 아래와 같이 지정할 수 있다.
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // X
ReadonlyArray<T>
타입으로 배열도 수정하 수 없도록 지정할 수 있다.
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // X
ro.push(5); // X
readonly
는 프로퍼티에 사용하고, const
는 변수에 사용한다.
초과 프로퍼티 검사 (Excess Property Checks)
지정한 타입 외에 다른 프로퍼티가 오게되면, Typescript는 코드에 버그가 있다고 판단한다.
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
let mySquare = createSquare({ colour: "red", width: 100 }); // X 에러
위 검사를 피하는 방법은 타입 단언
을 사용하는 것이다.
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
하지만 타입 단언보다는, 추가 프로퍼티가 있다고 확신한다면 문자열 인덱스 서명(string index signature)
을 사용하는 것이 더 나은 방법이다.
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
위에서 방법을 제시했지만, 검사를 피하는 방법을 시도하는 것보다는 타입 정의 자체를 수정하는 것이 가장 좋다.
함수 타입 (Function Types)
함수 타입을 기술하기 위해, interface
에 호출 서명(call signature)
을 전달한다.
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
위와 같이 사용되며, 매개변수의 이름이 같을 필요는 없다.
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1; // boolean을 반환하지 않는다면, 에러가 난다.
}
인덱서블 타입 (Indexable Types)
함수 타입을 설명하는 방법과 유사하게, a[10]
이나 ageMap["daniel"]
처럼 타입을 인덱스로 기술할 수 있다. 인덱서블 타입은 인덱싱 시, 반환 유형과 함께 객체를 인덱싱하는 데 사용할 수 있는 타입을 기술하는 인덱스 시그니처(index signature)
를 가지고 있다.
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
위 StringArray
인덱스 서명은 number
로 색인화 되며 string
을 반환할 것을 나타낸다.
"사전" 패턴을 기술하는데 강력한 방법이지만, 모든 프로퍼티가 반환 타입과 일치하도록 강제한다.
interface NumberDictionary {
[index: string]: number;
length: number; // O
name: string; // X 에러
}
인터페이스 확장하기 (Extending Interfaces)
인터페이스도 클래스처럼 확장(extend)이 가능하며, 이는 재사용성에 유연함을 준다.
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
하이브리드 타입 (Hybrid Types)
몇몇 타입의 조합으로 동작하는 객체를 볼 수 있는데, 아래는 그 예제이다.
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = (function (start: number) { }) as Counter;
counter.interval = 123;
counter.reset = function () { };
return counter;
}
'스터디' 카테고리의 다른 글
[Typescript] 리터럴 타입 (0) | 2023.06.10 |
---|---|
[Typescript] 함수 (0) | 2023.06.10 |
[Typescript] 기본 타입 (0) | 2023.06.09 |
[UX] 도널드 노먼의 UX 디자인 특강 (9장, 후기) (0) | 2020.09.01 |
[UX] 도널드 노먼의 UX 디자인 특강 (7~8장) (0) | 2020.08.26 |