홍열 2022. 2. 18. 14:23
728x90

01. Wath art Interfaces

어떤 type을 만들어 내는 방식

예전에는 내부적으로 숨겨져있고, 외부적으로 드러나는 호출 방식 

내부적인것과 관계없이 외부적으로 들어나는 객체의 사용방식

 

//interface가 없으면
function hello2(person:{name:string, age:number}): void{
    console.log(`hi my name ${person.name}, age is ${person.age} `);
}


//interface 사용하면...
interface Person1 {
    name:string,
    age:number
}

function hello1(person:Person1): void{
    console.log(`hi my name ${person.name}, age is ${person.age} `);
}

const p1:Person1 = {
    name:"Mark",
    age:39
}

hello1(p1)
//사실 {name:string, age:number} 로만 호출도 가능하다. 구조가 같아서 호출 가능
//근데 이 부분을 interface으로 만들면 더 깔끔하다.
hello1({name:"Qwe", age:45})

타입스크립트에서는 interface가 중요하다.

javascript에서는 없는 문법이며, 컴파일 했을 때 javascript에는 나오지 않는다.

컴파일 타임에만 필요하다. 컴파일 타임에 문제가 없는지 관계를 규명한다.

 

컴파일 결과 (javascript)

"use strict";
function hello1(person) {
    console.log(`hi my name ${person.name}, age is ${person.age} `);
}
const p1 = {
    name: "Mark",
    age: 39
};
hello1(p1);
hello1({ name: "Qwe", age: 45 });

 

02. Optional Property(1)

항상 필요한 property가 아니고, 필요에 따라서 있을 수도 있고, 없을 수도 있는 property

interface Person2 {
    name:string; 
    age?:number; //?달아 optional을 표현
}

function hello(person:Person2):void {
    console.log(`hello person2 name ${person.name}입니다.`)
}

hello ({name:"hong", age:123})
hello({name:"qwe"}) //Person2에 age를 않넣어줘도 오류가 안난다. optional이기 때문에

const a1:Person2 = {
    name:"hh"
}
hello(a1)

03. Optional Property(2)

interface에 optional type을 넣는 다른 방법

indexable type ...

문법은 

[index:string]:type

a['index] 와 같은 의미...어떤것을 프로퍼티 이름으로 지정할 수 있고, 

근데 사용하는 쪽에서는 호출하는 쪽 구조를 알아야되서 잘 안쓸수도 있겠다는 생각이 든다....

interface Person3 {
    name:string;
    age?:number;
    [index:string]:any; //어떤 이름의 프로퍼티가 와도 괜찮아....indexable type
}

function hello3(person:Person3):void {
    console.log(`Hello ${person.name}`)
    console.log(person.father)
    console.log(person['father'])
    console.log(person.mother)
}

const p31:Person3 = {
    name:'Mark',
    age:39,
};

const p32:Person3 = {
    name:"hong",
    systers:['A', 'B', 'C'] //[index:string]:any에 대응되는 부분
}

const p33:Person3 = {
    name:"Bob",
    father : p31,
    mother:p32
};
hello3(p33)

04. function in interface

interface 안에 함수를 정의하는 방법 

hello()을 객체를 정의하는 곳에서 같이 만들어야한다. p41, p42 참고

array function에서는 this를 사용할 수 없다. 

interface Person4 {
    name:string;
    age:number;
    hello():void //hello를 객체에서 만들어내야한다.
}

const p41:Person4 = {
    name:'Mark',
    age:39,
    //만드는 방법 1
    //hello의 타입을 function으로 지정 
    hello:function():void {
        console.log(`hello ${this.name}`)
    }
}

const p42:Person4 = {
    name:'Mark',
    age:39,
    //만드는 방법 2
    //hello를 ()로 사용하는 방법
    hello():void {
        console.log(`hello ${this.name}`)
    }
}

// const p43:Person4 = {
//     name:'Mark',
//     age:39,
//     //만드는 방법 3, arrow function
//     //화살표함수는 this를 사용할 수 없다..에러에러에러!!
//     //global this를 가르킨다
//     hello:():void  => {
//         console.log(`hello ${this.name}`)
//     }
// }

p41.hello()
p42.hello()

05. class implements interface

interface를 사용해서 클래스를 구현하는 방법...

java에서 많이 썼던것 같음...

interface는 컴파일 타임에서만 사용

클래스는 javascript의 feature로 들어가 있음

interface에 있는 내용을 바탕으로 클래스를 만들어 내는 것 

interface IPerson1 {
    name:string;
    age?:number;
    hello():void;
};

class Person implements IPerson1 {
    name: string;
    age?: number | undefined; //없어도 큰 문제가 없다.
    hello(): void {
        //throw new Error("Method not implemented.");
        console.log(`Class Person hello ${this.name}`)
    }

    constructor(name:string) {
        this.name = name
    }
}

//클래스 또한 타입처럼 사용가능

//Person이 IPerson1을 구현했기 때문에 아래와 같이 사용해도 된다.
//const person:IPerson1 = new Person('Hong');
const person = new Person('Hong');
person.hello()

oop에서 interface만 노출하고 구현은 노출하지 않는 방법..

06. interface extends interface

interface 끼리 상속하는 방법...

interface IPerson2 {
    name:string;
    age?:number
}

interface IKorea extends IPerson2 {
    city:string;
}

//IKorea는 IPerson2를 확장하는것

const k:IKorea = {
    name:"Hong",
    city:"seoul"
};

console.log(k.name, k.city)

07.  function interface

함수를 곧 interface로..

age는 optional이니까 있어도, 없어도 상관없고

대신 구현하는 곳...즉 function(name:string, age:number)로 쓰면 에러가 난다. 

이유는 interface와 function이 맞지 않다...

interface쪽에는 number | undefined이고 function에 있는건 number이기때문에 

더 큰 타입을 작은 타입에 넣지 못하기 때문이다...

//helloperson을 사용하는 객체는 (name:string, age?:number):void 형태로 작성되어야한다.
interface HelloPerson {
    (name:string, age?:number):void
}

//helloPerson은 뒤에 따라오는 function이하를 보는게 아니라 HelloPerson interface를 본다. 
//interface와 type이 맞아야 한다...
//그래서 function(name:string, age:number)는 에러이다. 
//interface의 age는 number | undefinded 타입이고, 
//function의 age는 number다...

const helloPerson:HelloPerson = function(name:string) {
    console.log(`helloPerson ${name}`)

}

helloPerson('Mark', 40)

08. Readonly interface properties

interface Person8 {
    name:string;
    age?:number;
    readonly gender:string;
}

const p81:Person8 =  {
    name:'Mark',
    gender:'male'
};

//error
//readonly 타입에 변경하므로...
//p81.gender = 'female'

09. type alias vs interface

추가적으로 읽어볼 블로그 

https://poiemaweb.com/typescript-alias

 

TypeScript - Type Alias | PoiemaWeb

 

poiemaweb.com

https://joonsungum.github.io/post/2019-02-25-typescript-interface-and-type-alias/

 

TypeScript에서 Type을 기술하는 두 가지 방법, Interface와 Type Alias

타입스크립트를 사용하기 시작한 뒤로 type을 기술할 때, 일반적인 상황에서는 특별한 고민 없이 interface를 사용하고 있었다. TypeScript 공식 문서에서 특별한 상황이 아니라면 interface의 사용을 권

joonsungum.github.io

https://poiemaweb.com/typescript-interface

 

TypeScript - Interface | PoiemaWeb

인터페이스는 일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다. 인터페이스는 여러가지 타입을 갖는 프로퍼티로 이루어진 새로운 타입을 정의하는 것과 유사하다.

poiemaweb.com

//function을 표현하는 방법
//type alias
type EatType = (food:string) => void;

//interface 
interface IEat {
    (food:string):void;
}

//array를 표현하는 방법
//type alias
type PersonList = string[];

//interface
interface IPeronList {
    [index:number]:string; //indexable type
}

//intersection

interface ErrorHandling {
    success:boolean;
    error?:{message:string};
}
interface ArtistsData {
    artists:{name:string}[]
}

//type alias
type ArtistsResponseType = ArtistsData & ErrorHandling
//interface
interface IArtistsResponse extends ArtistsData, ErrorHandling{}

let art:ArtistsResponseType;
let iar:IArtistsResponse;


//union type

interface Birt {
    fly():void;
    layEggs():void;
}
interface Fish {
    swit():void;
    layEggs():void;
}
// type은 union 가능...
type PetType = Birt | Fish;

//union type은 extends나 implements 불가
//어느 타입인지 혼동된다...타입이 두개잖아...
// interface IPet extends PetType {}
// class Pet implements PetType {} 


//Declaration Mergin - interface
interface MerginInterface {
    a:string
}
interface MerginInterface {
    b:string
}
//두개의 interface가 이름이 같으므로 하나로 합쳐진다..
let mi:MerginInterface;


//type alias 는 merging가 불가 
//같은 이름이면 에러 남
// type MergingType = {
//     a:string;
// }
// type MergingType = {
//     b:string;
// }