[TS] 기초(3)
interface
-
여러가지 타입을 갖는 프로퍼티를 갖는 새로운 타입 정의
-
일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용가능
-
모든 메서드는 '추상 메서드' (단, abstract 키워드를 사용하지 않음)
interface User {
[grade: number]: 'A' | 'B' | 'C' | 'D';
}
let user: User = {
1: 'A',
4: 'D'
}
사용이유
-
협업하여 개발시 공통적으로 사용되는 부분에 대해 미리 정의를 함
-
추후 코드를 합칠 때 효율적
Property
선택적 프로퍼티
?가 붙는 경우는 반드시 정의할 필요 없다.
interface User {
userName: string;
age?: number;
address?: string;
}
let user: User = {
userName: 'ddoni'
}
읽기전용 프로퍼티
readonly가 붙는 경우는 처음 정의한 후 변경이 불가능하다.
interface 확장
interface를 확장할 때 extends 예약어를 사용한다.
interface Person {
name: string;
age?: number;
}
interface Developer extends Person {
type: 'frontEnd' | 'backEnd';
}
const developer: Developer = {
name: 'ddoni', // 상속한 프로퍼티를 꼭 정의
type: 'frontEnd'
}
클래스에서도 interface를 상속할 수 있으며 이 경우에는 impelements 예약어를 사용해야 한다.
다중 interface 확장
콤마(,)를 사용하여 다중 인터페이스 확장이 가능하다.
interface Car {
color: string;
wheels: number;
start(): void;
}
interface Toy {
name: string;
}
interface ToyCar extends Car, Toy {
price: number;
}
let myCar: ToyCar = {
color: 'red',
wheels: 3,
start: () => {
console.log('start');
},
name: 'ddoni',
price: 10000
}
함수 타입
인터페이스는 함수 타입도 정의해줄 수 있다.
interface SquareFunc {
(num: number): number;
}
const squareFunc: SquareFunc = function(num: number): number {
return num*num;
}
덕 타이핑 (Duck typing)
-
인터페이스를 구현했다고해서 타입 체크를 통과하는 유일한 방법이 아님
-
타입 체크에서 중요한 것은 값을 실제 가지고 있느냐
케이스 1)
- 인터페이스에서 정의한 프로퍼티나 메소드를 가지고 있다면 그 인터페이스를 구현한 것으로 인정하며 이러한 것들을 덕 타이핑이라 한다.
interface IDuck {
quack(): void
}
class MallardDuck implements IDuck {
quack() {
console.log('Quack!');
}
}
class RedheadDuck {
quack() {
console.log('q~uack!');
}
}
function makeNoise(duck: IDuck):void {
duck.quack();
}
makeNoise(new MallardDuck());
makeNoise(new RedheadDuck()); // 오류가 나지 않는다.
케이스 2)
- 인터페이스를 변수에 사용할 경우에도 덕 타이핑은 적용된다.
interface IPerson {
name: string
}
function sayHello(person: IPerson): void {
console.log(`hello ${person.name}`);
}
const me = { name: 'Lee', age: 18 };
sayHello(me); // 변수 me에는 name이라는 값이 있기 때문에 패스가 된 것
sayHello({ name: 'error', age: 19 }); // 이거는 또 오류..
Generic
타입을 지정하여 선언하기 어려운 경우에 사용하며 선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있다.
사용이유
-
재사용성이 높은 함수와 클래스를 생성할 수 있다.
-
오류를 쉽게 포착할 수 있다. ( any타입은 컴파일 시 타입을 체크하지 않는다 )
class Stack {
private data: any[] = [];
constructor() {}
push(item: any): void {
this.data.push(item);
}
pop(): any {
return this.data.pop();
}
}
const myStack = new Stack();
myStack.push(1);
myStack.push('a');
myStack.pop().substring(0);
myStack.pop().substring(0); // 오류 발생
위와 같은 경우 타입에 따라 새로운 클래스를 생성할수도 있지만 여러가지 타입이 필요한 경우 일일이 생성하기는 어렵기 때문에 이럴 때 Generic을 사용하면 유용하다.
class Stack<T> {
private data: T[] = [];
constructor() {}
push(item: T): void {
this.data.push(item);
}
pop(): T | undefined {
return this.data.pop();
}
}
const myStack1 = new Stack<number>(); // number 타입만
const myStack2 = new Stack<string>(); // string 타입만
함수에서의 Generic
function toPair<T, U>(a: T, b: U): [T, U] {
return [a, b];
}
toPair<string, string>('1', '2');
toPair<string, number>('1', 2);
인터페이스에서의 Generic
interface Mobile<T> {
name: string;
price: number;
option: T;
}
const m1: Mobile<object> = {
name: 's1',
price: 1000,
option: {
color: 'red'
}
}
const m2: Mobile<string> = {
name: 's1',
price: 1000,
option: 'none'
}
interface GenereicLogTextFn1 {
<T>(text: T): T;
}
function logText<T>(text: T): T {
return text;
}
let myString1: GenereicLogTextFn1 = logText;
interface GenereicLogTextFn2<T> {
(text: T): T;
}
let myString2: GenereicLogTextFn2<string> = logText;
Union Type
OR 연산자와 같이 A 이거나 B이다
라는 의미의 타입을 의미한다. ( | 사용 )
function padLeft(value: string, padding: string | number) { // Union Type
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${typeof padding}'.`);
}
padLeft("Hello world", 4); // returns " Hello world"
padding 파라미터에 any타입으로 선언하면 에러를 감지하지 못하지만 union type으로 선언한다면 string 이거나 number 타입 이외에는 에러를 감지한다.
Intersection Type
여러 타입을 모두 만족하는 하나의 타입을 의미한다. ( & 사용 )
interface ErrorHandling {
success: boolean;
error?: { message: string };
}
interface ArtistsData {
artists: { name: string }[];
}
type ArtistsResponse = ArtistsData & ErrorHandling; // Intersection Type
const handleArtistsResponse = (response: ArtistsResponse) => {
if (response.error) {
console.error(response.error.message);
return;
}
console.log(response.artists);
};
handleArtistsResponse 함수의 매개변수인 ArtistsResponse는 ArtistsData & ErrorHandling 타입에 접근 가능
네트워크 에러 핸들링 시 유용하다고 함.
Reference
Author And Source
이 문제에 관하여([TS] 기초(3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jiseong/TS-기초3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)