공부블로그

Typescript 타입, 인터페이스, 함수 본문

공부하기

Typescript 타입, 인터페이스, 함수

떠어영 2022. 11. 30. 18:36

( GitBook을 보고 정리한 내용입니다 )

타입 

기본 내장 타입 (in Javascript)

  • number
  • string
  • boolean
  • symbol
  • null
  • undefined
  • object

+  다른 중요한 타입

 unknown  최상위 타입.
 never  하위 타입.
 객체 리터럴  예, { property: Type }
 void  리턴 타입으로 사용하기 위해 의도된 undefined 의 서브타입.
 T[ ]  수정가능한 배열들, 또한 Array<T> 으로 사용가능
 [ T , T ]   요소의 타입과 개수가 고정, 수정 가능한 튜플
 ( t : T ) => U  함수

 

  • Enum (열거) : 0부터 시작하여 멤버들의 번호를 매긴다. 
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
  • Any : 알지 못하는 타입을 표현
  • Never: 절대 발생할 수 없는 타입. 함수에서 항상 오류를 발생시키거나 절대 반환하지 않는 반환 타입
  • 타입 단언 Type assertion
//angle-bracket
let strLength: number = (<string>someValue).length;
//as
let strLength: number = (someValue as string).length;

 

※ 유의사항

 

1. 함수 구문에는 매개변수 이름이 포함된다

let fst: (a: any, d: any) => any = (a, d) => a;
// 또는 좀 더 정확하게 말하자면:
let snd: <T, U>(a: T, d: U) => U = (a, d) => d;

2. 객체 리터럴 타입 구문은 객체 리터럴 값 구문과 유사하다

let o: { n: number; xs: object[] } = { n: 1, xs: [] };

 

인터페이스 

Typescript 의 핵심 원칙 중 하나 : 타입 검사가 값의 형태에 초점 → 덕 타이핑 Duck typing

프로퍼티들의 순서를 요구하지 않고, 최소한 필요한 프로퍼티가 있는지와 타입이 잘 맞는지만 검사한다.

function printLabel(labeledObj: { label: string }) {
    console.log(labeledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"}; //최소한의 프로퍼티인 string이 존재하므로 ok
printLabel(myObj);

선택적 프로퍼티 → option bags (인터페이스의 모든 프로퍼티가 아닌 몇 개의 프로퍼티만 채워 함수에 전달하는 경우)

//선택적 프로퍼티를 가지는 인터페이스
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"});

초과 프로퍼티 검사 (excess property checking) : 객체 리터럴이 다른 변수에 할당될 때나 인수로 전달될 때 실행

                                                                                "대상 타입"이 갖고 있지 않은 프로퍼티를 갖고 있으면 에러 발생

interface SquareConfig {
    color?: string;
    width?: number;
}

function createSquare(config: SquareConfig): { color: string; area: number } {
    // ...
}
// error: Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
let mySquare = createSquare({ colour: "red", width: 100 });

↓  그나마 나은 해결법 = 타입 단언 

let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

 

- 함수 타입 인덱서블 타입을 기술할 수 있고 클래스에 implement될 수 있다.

 

interface SearchFunc { //함수 설명 인터페이스
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc; //타입

mySearch = function(source: string, subString: string) {//구현
    let result = source.search(subString);
    return result > -1;
}

- 인덱서블 타입

interface StringArray { //인덱스 인터페이스
    [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];

 

함수

// 기명 함수
fucntion add(x, y) {
  return x + y;
}

// 익명 함수
let myAdd = function(x, y) { return x + y };
let myAdd = (x, y) => { x + y } // 화살표 함수

모든 매개변수가 함수에 필요하다고 가정한다. 그래도 null이나 undefined는 매개변수로 가질 수 있다. 

선택적 매개변수를 원한다면 매개변수 이름 끝에 ? 를 붙인다

function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

유저가 값을 제공하지 않거나 undefined로 했을 때에 할당될 매개변수의 값을 정해놓을 수도 있다 = 초기화 값

function buildName(firstName: string, lastName = "Smith") {
    return firstName + " " + lastName;
}

나머지 매개변수 : 얼마나 많은 매개변수를 취할지 모를 때 ...을 사용해서 무한한 매개변수로 취급한다.

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

잘못된 this 사용을 잡아낼 수 있다.

  • this의 개념

객체지향 프로그래밍에서 객체는 상태(state)를 나타내는 프로퍼티와 동작(behavior)을 나타내는 메서드를 하나의 단위로 묶은 자료 구조다. 동작을 나타내는 메서드는 자기 자신이 속한 객체의 상태를 참조하고 변경할 수도 있어야 한다. 이 때, 자기 자신이 속한 객체를 참조하기 위한 식별자가 this다.  this 는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 식별자다.

  • this의 결정 방식

다른 언어들과는 다르게 자바스크립트에서 this는 함수가 호출되는 방식에 따라 동적으로 결정된다. 어떻게 선언되었든지 간에 호출을 어떻게 하느냐에 따라 this가 가리키는 객체가 다를 수 있다. 함수 호출 방식 4가지에 따라 this 바인딩이 달라진다.

함수 호출 방식 this 바인딩
일반 함수 호출 전역 객체
메서드 호출 메서드를 호출한 객체
생성자 함수 호출 생성자 함수가 생성할 인스턴스
Function.prototype.apply/call/bind 메서드에 의한 간접 호출 해당 메서드의 첫 번째 인수로 전달한 객체

일반 함수로 호출할 때 전역 객체에 this 바인딩이 되는 건 중첩 함수(다른 함수 내부에서 정의된 함수)여도 마찬가지고, 콜백이어도 마찬가지다. 

const obj = {
    func1 : function(){
        console.log('obj',this); // 메서드 호출이므로 메서드를 호출한 객체에 바인딩 : { func1: [Function: func1], func3: [Function: func3] }

        const func2 = function(): void { // 중첩된 내부 함수정의
            console.log('global',this); // 일반 함수 호출이므로 전역 객체에 바인딩 : Object [global]
        }
        func2()
    },
    func3: function( func4: () => void ){ //콜백함수를 인자로 받는 메서드
        console.log('method',this) // 메서드 호출이므로 메서드를 호출한 객체에 바인딩 : { func1: [Function: func1], func3: [Function: func3] }
        func4() //콜백함수 호출 = 일반 함수 호출이므로 전역 객체에 바인딩 : Object [global]
        
        const func5 = () => console.log(this) //화살표 함수 => obj에 바인딩
        func5()
    }
};
function func4(): void{
    console.log('callback',this)
}
obj.func1(); 
obj.func3(func4)

전역 객체에 this 바인딩 되는 문제를 해결하기 위한 방법이 바로 "화살표 함수" 이다. 화살표 함수는 함수 자체의 this 바인딩을 갖지 않고, 스코프 체인을 통해 상위 스코프의 this를 참조하기 때문이다.

 

 

리터럴 타입 /  유니언( | )과 교차 타입( & )/  열거형 (enum)

  • 열거를 적은 값으로 직관적으로 제한하기 위해 적용하는 것이 리터럴 타입(Literal Type)이다.
type Easing = "ease-in" | "ease-out" | "ease-in-out";

class UIElement {
  animate(dx: number, dy: number, easing: Easing) {
    if (easing === "ease-in") {
      // ...
  • 유니언 타입은 여러 타입 중 하나가 될 수 있는 값을 의미한다.
function padLeft(value: string, padding: string | number) {
  // ...
}
  • 교차 타입은 여러 타입을 하나로 결합한다.
interface ErrorHandling {
  success: boolean;
  error?: { message: string };
}

interface ArtworksData {
  artworks: { title: string }[];
}

interface ArtistsData {
  artists: { name: string }[];
}

// 이 인터페이스들은
// 하나의 에러 핸들링과 자체 데이터로 구성됩니다.
type ArtworksResponse = ArtworksData & ErrorHandling;
type ArtistsResponse = ArtistsData & ErrorHandling;
  • 열거형의 목적은 특정 프로퍼티를 자료형보다는 값(혹은 값의 집합)으로 제한하고자 하는데 있다. 

enum 키워드로 선언하며, { } 안에 자료형을 나열한다.

enum Response { // 숫자 열거형
    No = 0,
    Yes = 1,
}

enum Direction { //문자 열거형
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}