변수, 함수, 클래스에 타입 체크를 위해 사용됨
직접 인스턴스를 생성할 수 없으며 모든 메소드가 추상 메소드지만 abstract는 사용할 수 없다.
타입의 이름을 짓고 코드 안의 계약을 정의한다.
function hi(obj: {name: string}){
console.log(obj.name);
}
let person = {name: "bibi"};
hi(person);
interface Itype{
name: string
}
function hi(obj:Itype){
console.log(obj.name);
}
let person = {name: "bibi"};
hi(person);
Interface를 추가해 함수 매개변수의 프로퍼티를 정의할 수 있다.
컴파일러는 필수 요소 프로퍼티의 유무와 프로퍼티 타입에 대해 검사한다.
interface IType{
color?: string
width?: number
}
interface IType{
readonly x: number
readonly y: number
}
let point: Point = {x: 10, y: 20};
point.x = 5; // error
=> const와 공통점: 생성 후 배열을 변경하지 않음을 보장
=> const와 차이점: 변수는 const, 프로퍼티는 readonly
let arr: number[] = [1, 2, 3, 4];
let readonly_arr: ReadonlyArray<number> = arr;
readonly_arr.push(5) // error
인터페이스는 함수, 클래스에서 사용가능
interface IType{
(name: string, num: number):boolean
}
let hiName: IType
hiName = function(na, nu){
if(na.string === nu) retrun true
else return false
}
interface Itype {
name(): void
}
class person implements Itype {
name(): void{
console.log("bibi");
}
}
interface Itype {
name(): void
}
interface baby extends Itype {
speed: number
}
class person implements Itype {
name(): void{
console.log("bibi");
}
}
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;
}
객체가 할 수 있는 행위들을 전략으로 만들어두고 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 수정이 가능하도록 만든 패턴
코드가 수행될 때 타입을 명시하며, 작성 시에는 식별자를 써서 아직 정해지지 않은 타입을 표시
일반적으로 식별자는 T, U, V를 사용하거나 필드 이름의 첫 글자를 사용
재사용성이 높은 함수와 클래스 생성 가능
여러 타입에서 동작 가능 및 코드의 가독성 향상
오류를 쉽게 포착 가능
any처럼 미리 타입을 지정하지는 않지만 타입을 체크해 컴파일러가 오류를 찾을 수 있다.
function person<T>(items: T[]): T[]{
return items.person();
}
const year: number[] = [12, 20, 33, 45];
const names: string[] = ["aie", "bibi", "chin", "dony"];
person<number>(year);
person<string>(names);
class Queue<T>{
protected data: Array<T>=[];
push(item: T){
this.data.push(item);
}
pop(): T|undefined{
return this.data.shift();
}
}
const numQueue = new Queue<number>();
numQueue.push(0);
numQueue.push("1"); // 의도하지 않은 실수 사전 검출 가능
numQueue.push(+"1"); // 실수 사전 인지 및 수정 가능
"|"를 사용해 두 개 이상의 타입을 선언
Generic 또한 여러 타입을 다룰 수 있으나 Union은 선언한 공통된 메소드만 사용 가능하며 리턴 값이 선언된 Union 타입으로 지정된다는 점에서 다르다.
// union
const hi = (person: string | number) => {
return person;
}
const person1 = hi("bibi");
const person2 = hi(20);
person1.length; // error
// generic
const hi = <T>(person: T) => {
return person;
}
const person1 = hi<String>("bibi");
person1.length; // no error
원하지 않는 속성에 접근하는 것을 막기 위해 Generic에 제약조건을 사용
특정 타입들로만 동작하는 Generic 함수를 만들 때 Generic T에 제약 조건 설정
const hi = <T extends string | number>(person: T):T => {
return person;
}
hi<String>("bibi");
hi<Number>(20);
// 다른 타입은 에러 발생
두 객체를 비교
const hi = <T extends object, U extends keyof T>(obj: T, key: U) => {
return obj[key]
}
hi({aie: 10, bibi: 20, ceci: 30}, "bibi");
U의 값인 "bibi"가 Generic T의 값 중 존재하므로 오류가 발생하지 않는다.
Generic T는 키 값이 aie, bibi, ceci만 존재하는 object이다.
객체를 생성하는 인투페이스만 미이 정의하고 인스턴스를 만들 클래스의 결정은 서브 클래스가 내리는 패턴
슈퍼 클래스가 있을 때 입력에 따라 하나의 서브클래스 인스턴스를 반환
슈퍼 클래스: 여러 개의 서브 클래스를 가진 클래스
interface Animals {
bark(): void
walk(): void
}
class Dog implements Animals {
bark(): void {}
walk(): void {}
}
class Cat implements Animals {
bark(): void {}
walk(): void {}
}
class Home {
static getInstance(type: String): Animals {
// Animals의 type이 추가될 때마다 case문도 추가해야함
switch (type) {
case "dog":
return new Dog();
default:
return new Cat();
}
}
}
const dog = Home.getInstance("dog");
const cat = Home.getInstance("cat");
interface Animals {
bark(): void
walk(): void
}
class Dog implements Animals {
bark(): void {}
walk(): void {}
}
class Cat implements Animals {
bark(): void {}
walk(): void {}
}
class Hamster implements Animals {
bark(): void {}
walk(): void {}
}
export class Home {
static getInstance<T extends Animals>(type: {new (): T}}: T {
return new type();
}
}
const dog = Home.getInstance("dog");
const cat = Home.getInstance("cat");