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

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

 

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

 

타입스크립트 (Typescript)

 

오 드디어 강의가 거의 끝이 나 보인다.!!!!

강의보고 이해하고 글한번 적고,, 다른것도 하다보니 되게 오래걸렸다.

다보고나면 뭐 하나 만들어보고 간단히 강의 훑고 react랑 typesctipt 같이 써봐야지!

 

진짜 의식의 흐름대로 글을쓰다보니 1회차부터 보니까 ㅋㅋㅋ 내가 헷갈림..ㅎㅎ

나중에는 공식문서보면서 좀 제대로 알아봐야겠다.

 

Typescript를 지원하는 패키지, 아닌 패키지

일단 typescript로 제작된 패키지도 있고 아닌애들도 있는데, redux같은 경우에는 typescript로 되어있어서 가져다쓰기 좋다고한다. 

redux git에 가서 보면 이렇게 Typescript로 작성되었다는 것을 알 수 있다.

 

DefinitelyTyped

만약 내가 쓰려는 패키지가 Typescript로 작성되어있지 않다면 definitelyTyped를 이용하자.

https://github.com/DefinitelyTyped/DefinitelyTyped

 

이 레퍼지토리는 많은 사람들이 모여서 지원안하는 패키지의 type을 만들어둔 곳이라고한다.

공식적으로 지원하는 것이 없을 경우 여기서 찾아보면된다고!

유명하지 않은 패키지같은 경우에는 없을 수도 있다고 한다.

types 폴더에서 react나 jQuery들을 확인할 수 있다.

install하는 방법은 cmd 창에 @types/ 로 시작하면된다.

npm i @types/jquery

 

Triple Slash 

패키지를 다운로드 받고 나면 d.ts파일에 아래와 같은 코드를 확인할 수 있는 경우가 있다.

이 경우는 다른 패키지를 참조하는 것을 나타내는데, 속성 값으로는 types와 path가 있다.

types에는 패키지의 이름을 적을 수 있고, path에는 경로를 적을 수 있다.

아래 코드와 같이 적혀있는 경우에는 symbol-observable을 참조하고 있다는 뜻이다.

/// <reference types="symbol-observable" />

왜 import를 안하냐고 할 수 있는데, import도 가능하나 다른 패키지를 참조할때는 저렇게 사용한다고 한다.

보통 프로젝트 코드가 아닌 라이브러리를 만들때 사용한다고 한다.

 

 

Namespace

export as namespace d3;

namespace는 export한 것들을 d3라는 네임으로 묶어주는 것을 뜻한다.

export as namespace d3;

export * from 'd3-array';
export * from 'd3-axis';

아래와 같이 되어있다면 d3-array에 export한 함수중에 max라는 함수가 있다면 아래와 같이 접근 할 수 있다.

d3.max

 

 

import * as 

import하자마자 export한다는 뜻이다.

import * as d3 from 'd3';

 

 

declare

타입이 없는 것을 새로 선언할 경우에 사용할 수 있다.

types라는 폴더를 생성하고 그 아래 d.ts파일을 생성하여 아래와 같이 can-use-dom 패키지의 d.ts파일을 생성해 줄 수 있다. 

// d.ts 파일
declare module 'can-use-dom'{
	const canUseDOM: boolean;
    export default canUseDOM;
}
// config 파일
{
	"compilerOptions" : {
    	"strict" : true,
        "lib" : ["EX5", "ES2015", "ES2017", "ES2018", "ES2019"],
        "typeRoots" : ["./types", "./node_modules/@types"]
    },
    "exclude" : ["*.js"]
}

types는 내가 만든 파일이 들어있는 폴더의 경로이며 node_modules는 definitelyTyped에서 받은 d.ts파일들이 있다.

 

아래와 같이 다양한 작업을 할 수 있다.

전역 객체 선언

export{}
declare global{
	interface Window{
    	//...
    }
    
    interface Error{
    	//...
    }
}

export{}를 한 이유는 글로벌인 경우 external모듈이어야하기 때문에(규칙) export를 사용하여 꼼수로 에러가 안나도록한다.

글로벌 객체를 확장하기 위해서는 external, ambient 모듈이어야한다.

아래처럼 ambient 모듈로 만들어도된다. namespace, interface를 통해 express의 request를 확장할 수 있다.

declare module 'connect-flash'{
	global {
    	namespace Express{
        	interface Request{
            	//...
            }
        }
    }
}

import express = require('express');

(모듈관련해서는 좀 더 자세히 알아봐야할 듯 싶다)

 

 

잘못된 d.ts파일이라면?

1.먼저 패키지 d.ts파일을 install해서 복사해준다.

// 예시는 connect-flash 모듈
npm i @types/connect-flash

2.패키지를 제거한다.

npm rm @types/connect-flash

3.내가 작성하려는 d.ts파일을 모아둔 폴더에 빈 파일을 생성하여 붙여넣는다.

4.잘못된 부분만 수정한다.

 

 

d.ts파일 옵션 - 라이브러리 만들때 사용하는방법

// config 파일
{
	"compilerOptions" : {
    	"strict" : true,
        "lib" : ["EX5", "ES2015", "ES2017", "ES2018", "ES2019"],
        "typeRoots" : ["./types", "./node_modules/@types"],
        
        // 옵션추가
        "declaration" : true,
        "declarationDir" : "./types"
    },
    "exclude" : ["*.js"]
}

그 후 npx tsc 하게되면 declarationDir 경로에 d.ts파일을 자동으로 생성해준다.

 

 

intersection

& 이것을 말한다.

둘다 만족하는 것을 뜻한다.

type A = string & number;

예제

interface A { 
	a : true
};

interface B{
	b : false
};

const c: A & B = {
	a: true,
    b: false
}

interface나 type aliases에서 사용할 수 있다.

interface A { 
	a : true
};

interface B{
	b : false
};

type C = {
	c : false
}

const d: A & B & C= {
	a: true,
    b: false,
    c: false
}

|는 하나만 만족해도된다.

interface A { 
	a : true
};

interface B{
	b : false
};

const c: A | Bㅌ= {
	a: true,
    b: true
}

코드의 중복을 막고 각각의 변수를 재사용하기 위해 좋다.

 

 

call, bind, apply

타입추론이 잘 안되는 메서드들이다.

타입스크립트가 업데이트되면서 새로운 옵션이 생겼다고 한다.

// config 파일
{
	"compilerOptions" : {
    	"strict" : true,
        
		// 옵션 추가
        "strictBindCallApply" : true,	
        
        "lib" : ["EX5", "ES2015", "ES2017", "ES2018", "ES2019"],
        "typeRoots" : ["./types", "./node_modules/@types"],
        "declaration" : true,
        "declarationDir" : "./types"
    },
    "exclude" : ["*.js"]
}

타입스크립트가 엄격해진다고한다.

 

 

TS유틸리티

Partial

// interface의 일부만 가져다가 사용할 때 사용한다. 
interface A {
	a: 'a',
    b: 123
}

const a: A = {
	a: 'a',
    b: 123
};

// b가없어도 에러가 나지 않는다.
const b: Partial<A> = {
	a: 'a'
}

Readonly

// 하나하나 넣어주면 너무 비효율적
interface A{
	readonly a: 'a',
    readonly b: 'b',
    readonly c: 'c'
};

// Readonly
interface B{
	a: 'a'
};

const b: Readonly<B> = {
	a: 'a'
}

그 외에 공식문서보고 쭉 읽어보자.

pick, omit 등..

 

 

데코레이터

클래스나 클래스의 기능을 수정할 수 있다.

중복되는 코드가 생겼을때 함수를 하나 만들어서 사용할 수 있다.

아직 정식 문법이 아니어서 옵션 값을 추가해준다.

// config 파일
{
	"compilerOptions" : {
    	"strict" : true,
        "strictBindCallApply" : true,	
        "lib" : ["EX5", "ES2015", "ES2017", "ES2018", "ES2019"],
        "typeRoots" : ["./types", "./node_modules/@types"],
        
        // 옵션 추가
        "experimentalDecorators" : true,
        
        "declaration" : true,
        "declarationDir" : "./types"
    },
    "exclude" : ["*.js"]
}

위에 적으면 클래스 데코레이터

메서드 옆에적으면 메서드 데코레이터라고 한다.

프로퍼티에 적으면 프로퍼티 데코레이터, 파라미터 옆이면 파라미터 데코레이터가 된다고 한다.

@makeGender
class Person{}

class Person{
	@validate title : string
}
// typeof Person안하고 Person만 적으면 인스턴스가 되버려서 꼭 typeof Person해야한다.
function makeGender(target: typeof Person){
	
    // 원본을 인자로 받아서 새로운 것을 extends 시켜서 내보낸다.
    return class extends target{
    	//...
    }
}

@makeGender
class Person{
	//....
}

@makeGender
class Person2{
	//....
}

 

데코레이터의 각각의 위치에 따라서 매개변수가 달라진다고 한다.

3번째 인자 값이 달라진다.

// 클래스 데코레이터
function readonly(target: any, key: any, descriptor: propertyDescriptor){
	//....
}

// 파라미터 데코레이터
function readonly(target: any, key: any, index: number){
	//....
}

 

 

Q&A 타입스크립트는 왜써요?

노드로 개발할 경우 서버가 죽는 경우가 생긴다.

보통어이없는 실수가 대부분이다.

타입스크립트는 코드 작성 시 에디터에서 한번 걸러주고 빌드시 두번 걸러줘서 안정성이 올라갈 수 있다.

자바스크립트는 런타입에서 오류가 나야 알 수 있다.

퍼포먼스가 좋아지는 일은 없다. 

안좋아지는 일도 없다 빌드하는 시간이 걸리기는 하지만 컴파일된 코드를 런타임에서 실행하기 때문에 퍼포먼스에는 이상이 없다.

 

 

+ Recent posts