일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- animation
- function
- vuex
- class component
- ConstraintLayout
- elementAt
- collection
- Service
- Filter
- map
- CLASS
- AWS
- list
- LiveData
- 생명주기
- mongoose
- react native
- Swift
- Foreign Key
- MINUS
- recyclerview
- enum
- Generic
- ReactNative
- lifecycle
- docker-compose
- Interface
- union
- docker
- Kotlin
- Today
- Total
개발 일기
Interface ? 본문
Interface을 사용하여 추상 메소드를 정의하여 코드의 약속을 지정할 수가 있습니다.
[간단한 예시]
interface LabeledValue {
label: string;
}
function printLabel(labeledObj: LabeledValue) {
console.log(labeledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
여기에서 출력 값은 다음과 같이 "Size 10 Object"입니다.
만약에 myObj에서 label값이 없으면 에러가 발생합니다.
개발을 하다보면 interface에서 모든 값들이 필수일 필요는 없습니다.
그럴 때 사용할 수 있는게 Optional property 입니다.
[예시]
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;
}
let mySquare = createSquare({color: "black"});
여기에서 interface에서 ?을 포함하지 않았으면 밑에 mySquare에서 color 와 width을 같이 넘겨줘야 에러가 발생하지 않습니다.
Readonly Properties
처음에 객체를 생성 한 후에 수정이 불가능 해야 할때가 있습니다. 그럴 때 사용하는게 Readonly Properties 입니다.
[예시]
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
Typescript에서는 Array<T>와 동일하지만 처음에 생성을 한 후에 내용을 변경하지 않아야 할때 사용 하는 ReadonlyArray<T>가 있습니다.
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!
a = ro as number[]; // Type assertion으로 변경했을 때에는 Override가 가능합니다.
readonly 와 const 중 차이는 readonly일 때는 객체를 주로 사용을 하고 const일 때는 변수일때 사용을합니다.
프로퍼티 접근 체크
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
let mySquare = createSquare({ colour: "red", width: 100 });
다음과 같은 코드가 있을 때 colour라고 잘 못 입력을 하였습니다. Typescript는 대상 타입이 없으면 에러가 발생합니다.
만약에 다음과 같은 코드가 정상적으로 돌아가기 위해서는 Type assertion을 사용하는 방법이 있습니다.
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
Functin Types
인터페이스는 프로퍼티를 가진 객체 이외에, 함수 타입을 선언하는데 이용될 수도 있습니다.
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;
}
리턴 값이 숫자 혹은 문자열 등 다른 타입인 경우 경고가 출력됩니다.
Class Types
C# 및 Java와 같은 언어로 인터페이스를 사용하는 가장 일반적인 방법 중 하나는 클래스가 특정 계약을 준수하도록 명시적으로 적용하는 것입니다. TypeScript에서도 가능합니다.
interface ClockInterface {
currentTime: Date;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
constructor(h: number, m: number) { }
}
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
위의 예제에서 setTime과 마찬가지로 클래스에 구현된 인터페이스의 메소드를 설명할 수도 있습니다.
인터페이스는 클래스의 public과 private이 아니라 public만을 기술할 수 있습니다. 그렇기 때문에 클래스를 사용하여 클래스 인스턴스의 private에 특정 타입이 있는지 확인할 수 없습니다.
Extending Interfaces
클래스처럼 인터페이스도 확장이 가능합니다.
[예제]
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
Hybrid Types
메서드와 프로퍼티 모두를 가진 하이브리드 타입의 인터페이스도 있습니다.
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
Interfaces Extending Classes
인터페이스가 클래스를 확장하면 멤버를 상속하지만 Implements은 상속하지 않습니다.
이 패턴은 private 및 protected 멤버도 상속합니다.
private 또는 protected 멤버가 있는 클래스를 확장하는 인터페이스는 해당 클래스 또는 해당 클래스의 하위 클래스에서만 구현 가능합니다.
[예시]
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() { }
}
class TextBox extends Control {
select() { }
}
// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
private state: any;
select() { }
}
위의 예제에서, SelectableControl은 private state 속성을 포함하여 Control의 모든 멤버를 포함합니다.
state는 private 멤버이기 때문에 Control의 자손만 SelectableControl을 구현할 수 있습니다.
왜냐하면 Control의 자손들만이 같은 선언에서 유래된 private state 멤버를 가질 것이기 때문입니다.
이는 private 멤버들이 호환 가능해야 한다는 요구 사항입니다.
Control 클래스 안에서 SelectableControl 인스턴스를 통해 private state 멤버에 접근할 수 있습니다.
효율적으로 SelectableControl은 select 메소드를 가진 것으로 알려진 Control과 같은 역할을 합니다.
Button과 TextBox 클래스는SelectableControl의 하위 타입입니다. (왜냐하면 둘 다 Control을 상속 받았고 select 메소드를 가졌기 때문입니다), 하지만 Image 클래스와 Location 클래스는 그렇지 않습니다.
'컴퓨터 언어 > Typescript' 카테고리의 다른 글
Literal Types ? (0) | 2020.05.03 |
---|---|
Function ? (0) | 2020.05.03 |
Class ? (0) | 2020.05.01 |
변수 선언 ? (0) | 2020.04.26 |
기본 Type ? (0) | 2020.04.18 |