인프런 타입스크립트  기초를 통해 공부중이며 제로초님의 유료강좌입니다.

코드를 통으로 가져오지는 않겠습니다.(내가 글을 쓰면서 복습하는게 목적이기때문에 필요한 부분만)

 

타입스크립트에 익숙하지않다면 자바스크립트로 먼저 코드를 작성하고 그 후에 타입스크립트로 변환하도록하자.

 

타입스크립트 (Typescript)

 

오늘은 class와 interface를 더욱 자세히 알아봤다.

클래스는 인터페이스의 확장형(심화)으로 보면 될 듯 하다고 한다.

 

로직에 대한 힌트

인터페이스를 보고 타입을 확인할 수 있기 때문에 해당 로직에 대한 힌트를 얻을 수 있다.

아래 코드에서 인터페이스를 보고 heeJ와 yoon이 div인 것을 알 수 있다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,

    // originData는 클래스
    originData : Example[]
    copyData : Example || null
}

const person = {
    heeJ : document.getElementById('memo-heeJ'),
    yoon : document.getElementById('memo-yoon'),
    originData : [],
    copyData : null
};

 

 

null과 undefined 구분

타입스크립트에서는 null과 undefined를 구분해줘야하는 경우가 있다.

그 경우는 바로 tsconfig.json에 설정에 따라서 인데, "strictNullCheckes" 설정 값에 영향을 받는다.

"strictNullCheckes"가 true일 경우에는 null과 undefined를 구분해주며 false일 경우에는 구분하지 않는다.

 

그리고

"strict"를 true로 설정한다면 기본으로 "strictNullCheckes"도 true가 된다.

{
    "compilerOptions" : {
        "strict" : true
        
        // 보이지는 않지만
        // "strictNullCheckes" : true
    }
}

그렇기 때문에 기본적으로 null과 undefined를 구분이 된다.

때문에 내 데이터가 없을 경우가 존재한다면 null 타입을 추가해줘야한다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
	
    // null을 작성해야한다.
    copyData : Example | null
}

 

만약에 "strict"를 "false"로 변경하게되면?

null을 따로 구분하지 않기 때문에 null을 적어줄 필요가 없다.

하지만 strict가 false이면 타입스크립트의 기능을 극대화해서 사용할 수 없기 때문에 비추한다.

하지만 예제를 보자.

{
    "compilerOptions" : {
        "strict" : false
    }
}
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]

	// null 제거
    copyData : Example
}

 

undefined를 작성하는 대신에 물음표로 대체할 수 있다.

// undefined 예시
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
    copyData : Example | undefined
}

// 물음표 예시
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
    copyData? : Example
}

 

"scrictNullChecks"가 true일때

null과 undefined를 구분하고 있으므로 물음표를 추가해도 undefined와 구분이 되므로 null을 작성해줘야한다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]

	// 물음표와 null 두개다 포함
    copyData? : Example | null
}

 

제로초님은 보통 자바스크립트로 코드를 짤 때, null은 빈 값을 의도적으로 넣었음을 알리기 위해 사용했다고 한다. 하지만 타입스크립트에서는 "structNullChecks" 때문에 undefined를 사용하는 경우가 많다고한다.

(물음표만 추가하면 되기에..)

 

 

인터페이스와 클래스

인터페이스는 클래스처럼 사용할 수 없다.

interface People{
    heeAge: number;
    yoonAge: number;
}

interFace Person{
    originData : People[],
    copyData? : People | null
}

// 이렇게 쓸 수가 없다.
new People();

아래처럼 클래스 표현이 가능하기는 하다고 한다.

interface People{
    new (yoon: string);
}

 

자바스크립트와 같이 constructor가 필요하며 자바스크립트와는 다르게 private, public, protected 키워드를 지원한다.

자바스크립트에서는 즉시 실행함수 + 클로져를 사용해서 키워드를 흉내냈었는데, 타입스크립트는 지원하고 있기 때문에 최대 장점이라고한다.

(최신문법에는 #을 붙이는 방법으로 지원한다고 한다.)

class Person{
	public age : number;
    protected name : string;
    private address : number;

    constructor(heeJAge, yoonAge){
        // ....
    }
}

const Person(22, 15);

// private로 선언한 address에는 접근이 안됨
Person.address;

private는 class외에 접근이 안되고 public은 모든 곳에서 접근이 가능하다.

protected는 해당 class, 상속받은 자식에서 접근이 된다. (부모에서는 안된다.)

class People{

  // 상속받는 Person에서 접근해야하기 때문에 protected로 선언
  protected heeJAge : number;
  protected yoonAge : number;

  constructor(name: string, age: number){
      // ...
  }
}

new People('hong', 17);

class Person extends People{
	// 여기서 heeJAge와 yoonAge에 접근이 가능하다.
}

 

만약 자바스크립트에서 해당 키워드를 사용해보고 싶다면 컴파일된 파일에서 해당 로직만 사용해봐도된다.

 

클래스에서 new 키워드로 인스턴스를 생성하여 접근하려고 할때 construct내부에 선언한 것을 if문 안에 넣었을 경우 변수의 타입을 인식못하는 경우가 생길수도 있다고한다. 이때는 undefined를 추가해주면된다.

class Person{
    protected value? : number;
    protected number?: number;
    
    constructor(a: boolean, b: boolean){
        if(a){

            // 상속을 하지말고 People코드를 여기에 적으면 물음표를 추가하지 않아도된다.
            return new People(b);
        }
    }
}

class People extends Person{
    private value: number;
    private number: number;
    constructor(mine){
        super(true, mine);
        
        if(true){

            // 상속에 if문안에 있는 이 this.value의 값을 타입스크립트가 모른다.
            this.value = 1;
            this.number = 2;
        }
    }
}

 

protected나 private 키워드를 사용했을 경우 인터페이스를 만드는 것은 말이 안된다고 한다.

protected와 private의 접근 제한을 생각해보자.

(인터페이스는 부모가 되므로 사용될 수 없다.)

 

 

클래스가 지켜야하는 규칙 implements

인터페이스를 구현해서 클래스의 모양을 잡아놓을 수 있다.

클래스는 인스턴스의 모양을 규정짓는거라면 인터페이스는 한단계 더 위에 있으며 클래스의 모양을 규정짓는다.

// 네이밍시에 앞에 I를 추가한다.
interface IName{
    //...
}

class People implements IName{
    //..
}

이때 클래스보다 인터페이스가 더 좁은 집합이어야한다.

범위를 생각해보면 인터페이스를 잘 만들었는지 알 수 있다. 적어도 같게 만들어야한다.

근데 implements는 실제 클래스가 필요없을 때 사용한다고 한다.

클래스의 모양을 정해주고 싶을때 사용한다고 하고 실제로 사용하고 싶다면 class로 변경하면된다.

또한 implements 말고 type aliases를 사용해도 된다.

 

 

 

인프런 타입스크립트  기초를 통해 공부중이며 제로초님의 유료강좌입니다.

코드를 통으로 가져오지는 않겠습니다.(내가 글을 쓰면서 복습하는게 목적이기때문에 필요한 부분만)

 

타입스크립트에 익숙하지않다면 자바스크립트로 먼저 코드를 작성하고 그 후에 타입스크립트로 변환하도록하자.

 

 

타입스크립트 (Typescript)

 

 

인터페이스(interface)란?

"

인터페이스는 변수나 함수, 클래스와 같은 객체에서 사용한다.

여러가지 타입을 갖는 프로퍼티로 이루어지며 새로운 타입을 정의할 수 있다.

인터페이스에 선언된 프로퍼티나 메소드를 통해 구현을 강제할 수 있으며 이것을 통해 일관성을 유지할 수 있도록 한다. 인터페이스는 클래스와 유사하나 직접 인스턴스를 생성할 수 없다. 또한 모든 메소드는 추상 메소드이다.

"

 

인터페이스로 변환하는 예제를 확인해보자.

const test = {
	a : 1,
	b : 2
} as const;

// interface
interface TEST{
    a : 1,
    b : 2
}

이때 as const로 선언한 test와 interface로 선언한 test가 같은지를 생각해봐야한다.

as const로 선언 후 마우스를 포커싱해보면 vscode에서 readonly라고 뜨는것을 확인할 수 있다.

붙이지 않아도 값을 고정할 수 있지만 as const와 동일한 결과가 아닌 예제를 보자.

interface TEST{
    a : string
    b : string
}

interface TEST{
    readonly a : string
    b : string
}

위의 예제처럼 상수 값이 아닌 경우를 넣게될 경우에 as const와는 똑같다고할 수가 없다.

이때 readonly 키워드를 붙여주어 as const와 동일하게 만들어줄 수 있다.

interface TEST{
    readonly a : 1,
    readonly b : 2
}

 

인터페이스의 줄바꿈은 콤마, 세미콜론, 아무것도 붙이지 않는 것이 가능하다.

// 콤마
interface TEST{
    a : 1,
    b : 2
}

// 세미콜론
interface TEST{
    a : 1;
    b : 2;
}

// 줄바꿈
interface TEST{
    a : 1
    b : 2
}

 

 

인터페이스의 특징으로는 상속이 있다.

상속받을 경우 extends를 사용하면된다.

interface TEST{
    readonly a : string
    b : string
}

// 이렇게 하면 TEST를 상속받아 오는 것
interface Example extends TEST{
    // TEST의 a, b 타입을 가지고 있다.
}

// TEST를 상속받은 Example을 통해 타입 선언
const Hi : Example = {
    // TEST a, b 타입을 적용
};

인터페이스 객체의 틀을 잡고 상속하는 점이 클래스와 비슷하다고 할 수 있다.

또한 같은 이름의 인터페이스를 여러개 생성할 수 있다.

이럴 경우 인터페이스들은 하나로 합쳐진것과 동일하다.

타인이 만든 라이브러리의 인터페이스에 문제가 생겼을때 수정을 하기 위함이거나 확장을 해야할 경우에 사용한다.

interface TEST {}

// ....

interface TEST{}

 

 

type aliases는 타입으로 선언하는 것이다.

타입은 인터페이스처럼 같은 네이밍으로 선언했다고 해서 합쳐지는 것이 아니고 여러개 선언시에 에러가 난다.

type Test = {};

 

인터페이스와 타입 에일리어스의 선언 방식의 차이

interface TEST {};

// '=' 이 들어가야한다.
type TEST = {};

타입이 더 넓은 범위, 인터페이스는 객체일때 많이쓴다고 한다.

타입도 물론 인터페이스를 대체하여 객체를 만들수도 있다고 한다. (하지만 결국 선호도의 차이일 수도 있다고했다.)

 

타입으로 커스텀 타입을 생성할 수 있다.

새로운 test라는 타입을 생성하였다. test의 타입은 string 또는 number다.

type test = string | number

 

type을 객체로 사용하는 예시

type test = {
    a : 'a' 
} | string;

// string값, 객체 둘 다 사용가능하다.
const example : test = 'hello';
const example : test = {
    a : 'a'
};

 

객체로 사용할때에는 인터페이스를 사용하는게 좋다는데, 타입은 나중에 복잡해질 경우 사용하게 된다고 한다.

(위에 말했듯 선호도 일수도 있다고 했다.)

유니언이 필요할 경우에 타입을 쓴다.

type test = {
    //..
} | string;

 

 

keyof

위에서 선언한 key, value 값을 아래에서 타입으로 사용하기 위해서는 keyof를 통해 쓸 수 있다.

key 예시

interface TEST {
    readonly orange : 'orange',
    readonly apple : 'apple'
}

// TEST와 같은 키를 return 받는 함수.
function get(o) : keyof TEST{
    // ...
}

 

반대로 value 값 예시

interface TEST {
    readonly orange : 'orange',
    readonly apple : 'apple'
}

// 인자값 o가 TEST의 value 값과 동일해야할때
function get(o ㅣ TEST[keyof TEST]) : keyof TEST{
    // ...
}

 

만약 불가피하게 어떠한 값이 들어올 지 모르게되는 경우에는 넓은 범위로 선언해준다.

하지만 엄격하게 사용하는 것이 좋기때문에 지양하는 것이 좋다.

// [key : string] : number
interface Example{
    a : 2,
    b : 3,
    [key : string] : number;
}

const example : Example = {
    a : 2,
    b : 3,
    c : 100
}

 

lib.es5.d.ts파일을 확인해보면 Object.keys()는 반환값이 string[]으로 고정되어있다.

따라서 에러가 생기는 경우가있다.

이때는 타입스크립트가 스스로 범위를 좁게 잡지 생기지 못하기때문에 강제로 넓은 범위로 넓혀주는 것이 좋다.

function TEST (o : Example[keyof Example]) : keyof Example {
	// as ['a', 'b', 'c'] 강제로 선언
    return (Object.keys(test) as ['a', 'b', 'c']).find((k) => test[k] === o);
}

또한 위의 코드에서 find메서드를 사용했는데, 이 메서드는 ES6에서 사용할 수 있으므로 tsconfig.json을 수정해줘야한다.

{
    "compilerOptions" : {
        "strict" : true,
        
        // ES5, DOM이 기본값이므로 그 이상의 값을 다 입력해주자. 
        // 이 코드는 아직까지 줄이기가 힘들다고 했다.
        "lib" : ["ES5", "ES6", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020", "DOM"]
    },
    "exclude" : ["*.js"]
}

 

또한 명령어 입력 시 tsconfig.json을 포함할 경우에 해당 파일이 무시되어 에러가나는 경우가 생기는데

이때 파일을 입력하지 않은채로 명령어를 입력해준다.

// cmd
npx tsc -w

 

find의 타입을 확인해보면 리턴 값이 T | undefined로 고정되어있는 것을 확인할 ㅜㅅ 있다.

이때는 아래와 같이 느낌표를 추가하여 해결할 수 있다.

느낌표를 입력하면 에러가 사라지는데, 느낌표는 타입시스템에서는 오류라고 말하지만 개발자가 그 코드를 보증하는 것이다. 이건 프로그래머의 재량이다. 느낌표가 없어서 실행이 안되는 경우들이 존재하는데 이때 사용할 수 있다. undefined나 null을 보증할 수 있다. (하지만 안쓰는 방법도 존재한다.)

function TEST (o : Example[keyof Example]) : keyof Example {
    return (Object.keys(test) as ['a', 'b', 'c']).find((k) => test[k] === o)!;
} 

 

 

this에러

화살표 함수가 아닐 경우에 발생하는 경우가 있는데, 이때 자바스크립트와 가장 크게 달라진다.

매개변수 첫번째 위치에 this 와 this의 타입을 선언해준다.

document.querySelectAll('button').forEach((btn) => {
    btn.addEventListener('click', function(this : HTMLButtonElement, e : Event){
            const my = this.textContent;
    });
});

타입스크립트는 html을 모르기 때문에 this.textContent가 string | null로 유추한다

lib.dom.d.ts파일을 보면 textContent에서 확인 할 수 있다.

 

타입스크립트가 스스로 추론하지 못하는 값들을 선언해줘야한다.

document.querySelectAll('button').forEach((btn) => {
    btn.addEventListener('click', function(this : HTMLButtonElement, e : Event){
       // TEST의 key값과 동일할 경우 as를 통해 타입 선언을 해준다.
       const my = this.textContent as keyof TEST;
   });
});

 

 

느낌표, if문, 꼼수를 통해 에러 보증하기

querySelector도 html을 인식하지 못하기 때문에 자바스크립트처럼 사용하면 에러가나게된다.

이때 lib.dom.d.ts파일에서 E | null로 유추하고 있음을 확인할 수 있다.

느낌표를 사용하여 에러를 막을 수 있다.

document.querySelector('#test')!.style.background = '';

또한 if문으로도 해결할 수 있다.

if문으로 감싸줄 경우 null이 아님을 보증하기 때문에 에러를 방지할 수 있다.

if(document.querySelector('#test')){
  document.querySelector('#test').style.background = '';
}

또 다른 방법으로 꼼수를 쓸 수도 있다.

근데 이렇게 하느니 느낌표를 쓰라더라.

if(!test){
    throw new Error('nope')
}
return test;

 

그 후 querySelector뒤에 style에서 에러가 또 발생하는데, querySelector는 E | null 이었다.

이때 E는 Element를 상속받는데, E는 style이 존재하지 않는다고 뜬다.

이때 제네릭으로 해결할 수 있는데, (아직 안배웠다)

현재 할 수 있는 방법으로는 as를 통해 형변환을 하는 방법이다.

HTMLDivElement는 style이 존재하고 Element는 style이 없기때문에 HTMLDivElement로 형변환을 해주자.

if(document.querySelector('#test')){
  document.querySelector('#test') as HTMLDivElement.style.background = '';
}

 

아직배우지는 않았지만 제네릭으로 썼을때는 아래와 같이 사용할 수 있다.

또한 변수에 담지않을 경우 문자열이 같다고 인식하지 않기때문에 변수에 담아 중복코드를 방지해주자.

// (X)
if(document.querySelector<HTMLDivElement>('#test')){
  document.querySelector<HTMLDivElement>('#test').style.background = '';
}

// (O)
const test = document.querySelector<HTMLDivElement>('#test')

if(test){
  document.querySelector<HTMLDivElement>('#test').style.background = '';
}

 

타입스크립트의 엄격함때문에 형변환을 해야하는 경우도 있다.

textContent는 string이기때문에 아래와 같이 형변환을 해줘야한다.

(document.querySelector('#test') as HTMLDivElement).textContent = String(point);

 

 

 

 

인프런 타입스크립트  기초를 통해 공부중이며 제로초님의 유료강좌입니다.

코드를 통으로 가져오지는 않겠습니다.(내가 글을 쓰면서 복습하는게 목적이기때문에 필요한 부분만)

 

 

타입스크립트 (Typescript)

 

any

배열을 만들고나서 마우스를 변수에 올려보면 타입이 any라고 뜬다.

const arr = [];

any 타입은 아무 타입이나 넣어도된다는 것을 의미한다.

const a: any = 'a다';
const a: any = 1;
const a: any = true;
const a: any = [];

any 타입을 선언하는 것은 자바스크립트와 같다고 볼 수 있는데, 남발한다면 타입스크립트를 쓰는 의미가 없으므로 최소한의 경우에 필요한 곳에 사용해야한다.

최소한의 경우란 보통 남이 만든 타입을 변경해야할 때라고 생각하면된다.

내가 생성한 .ts 파일같은 경우에는 타입을 쉽게 변경할 수 있지만 남이 만든 d.ts파일을 가져와서 사용하는 경우에는 선언이 잘못되어있을때, 문제가 생기게되면 any를 쓴다.(타입 정의 시 복잡도가 증가해서 문제가 생길때도 any를 쓴다.)

// d.ts
const a: number;

// .ts
// d.ts를 import했을때, 문제가 생긴다 
a.subStr();

웬만해서는 안쓰는게 좋다.

 

 

never

실무에서 보통 에러로 만나게되는 타입.

실수하는 부분의 대부분이 배열이라고 한다.

const arr = [];

위처럼 배열을 선언한 후 변수에 마우스를 올리게되면 any 타입을 유추해준다.

배열의 타입을 잘못선언한 예시를 보자.

const arr: [] = [];

이런 경우에는 push를 쓰게되면 never타입 에러가난다.

// 어떠한 요소도 못들어감
const arr: [] = [];

// 값을 넣게되면 에러가난다.
arr.push(3);

 

 

강제로 변수의 타입을 변경하는 법

라이브러리를 만들 경우에 타입을 강제로 변환해야하는 상황이 생긴다고한다.

as unknown as 타입

<타입><unknow> 

// d.ts
const str: number;

// string으로 강제로 선언1
(str as unknown as string).substr();

// string으로 강제로 선언2 (타입캐스팅 방법)
(<string><unknown>str).substr();

만약 타입이 부모-자식 관계일 경우에는 as unknow을 안써도 된다.

상속관계는 lib.dom.d.ts의 extends를 확인하면 알 수 있다.

const div = document.createElement('div');
div as HTMLElement;

 

 

 

 

인프런 타입스크립트  기초를 통해 공부중이며 제로초님의 유료강좌입니다.

코드를 통으로 가져오지는 않겠습니다.(내가 글을 쓰면서 복습하는게 목적이기때문에 필요한 부분만)

 

타입스크립트 (Typescript)

 

as const;

변수를 상수처럼 쓰고 싶다.

타입스크립트 전용 문법인 as const; 를 뒤에 붙이면 된다.

let str = 'haha' as const;
let arr = [true, 2, '3'] as const; 

변수에 마우스를 올렸을때 

let arr:readonly [true, 2,, '3'] 이라고 뜨는데, 여기서 새로운 타입 readonly를 볼 수 있다.

as const;로 선언할 경우 let이어도 재 정의시에 에러가 난다.

그렇다면 const로 선언하면 되지 않나? 라고 하는데,

const str = 'haha' as const;
const arr = [true, 2, '3'] as const;

이때 객체의 단점을 확인할 수 있다.

오브젝트 자체의 값을 변경할 수 는 없지만 오브젝트의 프로퍼티에 접근하여 값을 변경할 수 있기 때문이다.

const obj = { a : 'b' };

// (X)
obj = 'haha';

// 문제 발생
obj.a = 'a';

따라서 이런 경우 as const;를 선언해주면 배열이나 객체의 내부 값들도 상수로 만들 수 있다.

const obj = { a : 'b' } as const;

 

 

객체 object 타입 선언하기

object의 타입이 많이 존재할 수 있기 때문에 타입을 단순히 object라고 선언하지 않는다.

// (X)
const obj : object = { a : 'b' };

타입을 만들어서 선언해준다. 이때부터 코드가 길어져서 가독성이 안좋아진다.

const obj: {a : string } = { a : 'b' };

// (O)
obj.a = 'a';

// (X)
obj.a = 3;

그리고 타입을 선언했을때 아래와 같이 선언한 a, b에 대한 값을 모두 충족시켜야 에러가 발생하지 않는다.

// (X)
const obj: { a : string, b : number } = { a : 'b' };

// (O)
const obj: { a : string, b : number } = { a : 'b', b : 3 };

여기서 만약 값이 있을수도 있고 없을 수도 없다면 어떻게 할까?

왜냐하면 프로그래밍을 하다보면 나중에 값을 삽입하게 되는 경우가 있기 때문인데,

이때는 물음표를 넣어준다.

*중복코드의 느낌이 나는 경우가 생기기때문에 나중에는 인터페이스나 타입으로 빼게 된다고 한다.

const obj: { a : string, b? : number } = { a : 'b', b : 3 };

 

 

 

타입스크립트의 타입 enum

enum Color { Red, Green, Blue }
let c: Color.Green;

js로 컴파일하게되면 아래와 같이 나온다.

(function (Color) {
	Color[Color["Red"] = 0] = "Red";
	Color[Color["Green"] = 1] = "Green";
	Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));

enum은 각각의 단어에 숫자를 넣거나 반대로 넣어도 성립되게 만들어준다.

Color[0] === 'Red';
Color['Red'] === 0;

 

 

물음표의 역할

자바스크립트에서 물음표는 삼항연산자에 쓰인다.

타입스크립트에서는 옵션체이닝때 사용하는데, ?. 라는 것도 있다.

?.은 삼항연산자와 구분하기 위함이라고 한다.

const obj: { a : string, b? : number } = { a : 'b', b : 3 };
const a = abc?.name;

 

 

null과 undefined, void

자바스크립트의 null은 object인데, 이건 자바스크립트의 버그이므로 타입스크립트에서는 null의 타입은 null로 체크한다.

undefined는 undefined의 타입을 가지고 있다 void 0의 타입도 undefined이다.

const n = null;
const n = undefined;
const n = void 0;

 

 

함수에서 사용하기

함수에서 타입스크립트는 변수, 매개변수, 리턴 값에 타입을 붙일 수 있다.

// (매개변수) : 리턴 값에 대한 타입
function f(a: number, b: number): number | string {
    return a + b;
}

리턴 값이 없는 함수는 return undefined가 생략된 것이지만 이럴경우 타입을 void로 적으면 된다.

undefined로 작성하면 에러가 난다.

function f(a: number, b: number): void {
   console.log(a, b);
}

 

 

고차함수

함수가 고차함수를 리턴하는 경우 리턴되는 값의 타입을 작성하면된다.

함수의 타입은 리턴 값의 타입 자리에 적어준다.

// 함수 자체를 타입으로 쓸때
// (c: string) => number 함수 파라미터의 타입값과 함께 리턴 값을 적어줘야한다.
function f(a: number, b: number): (c: string) => number {
    return(c: string) => {
        return c;
    }
}

// 함수를 선언할때
function f(p: number): number{
    // ....
}

함수형 프로그래밍할때 고차함수를 많이 사용하는데, 

이러한 경우 때문에 가독성이 점점 안좋아지는 것이다.

function add(a: number, b: number): (c: string) => (d: string) => boolean {
    return (c: string) => {
        return (d: string) => {
            return false;
        }
    }
}

 

 

객체

자바스크립트는 타입이라는 개념이 없다.

따라서 오버로딩이 없다. (흉내내기일 뿐)

이때 타입스크립트는 타입이 존재하기 때문에 오버로딩이 구현된다.

// obj2의 타입
const obj2: {a: (b: number) => string} = {
    a(b: number){
        return 'hello';
    }
}

// 매개변수가 있어도되고 없어도 될때, 오버로딩일 경우 물음표를 추가해준다.
const obj2: {a: (b?: number) => string} = {
    a(b?: number){
        return 'hello';
    }
}

// 둘다 호출해도 에러가 안난다. 
// 만약 물음표를 추가하지 않았으면 에러가 난다.
obj.a();
obj.a(3);

 

 

 

+ Recent posts