타입스크립트의 모듈 시스템

타입스크립트 모듈은 전역 변수와 구분되는 자체 유효 범위를 가지며 export import와 같은 키워드를 사용하지 않으면 다른 파일에서 접근할 수 없다.

// app.ts
import{Todo} from './types'

var item:Todo = {
    title:'할 일 1',
    checked:false
}
export interface Todo{
    title:string;
    checked:boolean;
}

📑 referece

'TypeScript' 카테고리의 다른 글

타입추론, 타입단언, 타입가드  (0) 2021.08.01
class와 generic  (0) 2021.08.01
타입스크립트 - 변수와 함수 타입  (0) 2021.07.13
Why Typescript?  (0) 2021.07.12

타입추론

타입스크립트가 코드를 해석해 나가는 동작을 의미한다.

인터페이스와 제네릭을 이용한 타입 추론 방식


제네릭을 선언했을 때, 타입스크립트가 제네릭을 이용해 타입을 추론해 변수에 필요한 속성을 보장해준다.

복잡한 구조에서의 타입 추론 방식

DetailedDropdown에서 value와 tag가 제네릭 타입으로 정의해야 한다.

Best Common Type 추론 방식

Best Common Type은 타입스크립트가 타입을 해석하는 알고리즘
모든 타입을 union으로 묶어감

타입단언

Typescript의 타입 추론 기능은 매우 강력하지만 어쩔 수 없는 한계가 존재한다. 타입 단언은 타입스크립트 컴파일러가 실제 런타임에 존대할 변수의 타입과 다르게 추론하거나 너무 보수적으로 추론하는 경우에 프로그래머가 수동으로 컴파일러한테 특정 변수 타입에 대해 힌트를 주는 것이다. as 키워드를 사용한다.

타입 캐스팅과의 차이는 타입 캐스팅은 컴파일타임과 런타임에서 모두 타입을 변경시키지만 타입 단언은 오직 컴파일타임에서만 타입을 변화시킨다는 것이다.

아래의 예시에서 b=aa라고 했을 때 b를 any로 추론한다.

var aa;
aa = 20; // number로 할당
aa = 'a' // string으로 재할당

하지만 aa에 최종적으로 string을 할당했기 때문에 aa의 타입은 string이므로, as로 string 타입임을 단언하면 b를 string으로 추론을 하게된다.

ex] DOM API 조작에서 타입단언의 예

<div id="app">hi</div>

DOM API의 타입도 일반적으로 제공을 하지만 실제로는 DOM API를 사용하는 시점에 해당 element가 있다는 것을 보장하지 않는다. 사실상 null와 HTMLDivElement 타입을 갖게 되는 것이다.
따라서 아래와 같은 패턴으로 사용한다.

var div = document.querySelector('div') 


if(div){
  div.innerText;
}

타입 단언을 해주면 null 타입을 갖지 않게 되므로 아래와 같이 사용할 수 있다.

var div = document.querySelector('div') as HTMLDivElement;
div.innerHtext;

타입가드

타입가드는 타입 단언을 좀 더 깔끔하게 할 수 있도록 도와준다. 타입 가드는 런타임에서의 타입 체크를 컴파일러에게 알려주는 기능이다. is키워드를 사용한다.

interface Developerr{
    name:string;
    skill:string;
}

interface Personn{
    name:string;
    age:number;
}

function introduce() : Developerr|Personn { 
    return {name:'Tony', age:33, skill:'Iron Making'}
}

공통속성아 아닌 타입을 사용하기 위해서 타입단언을 이용해 아래와 같이 사용하면 가독성이 떨어진다.

if((tonytony as Developerr).skill){
    var skill = (tonytony as Developerr)
    console.log(skill)
}else if ((tony as Person).age){
    var age = (tonytony as Personn)
    console.log(age)
}

isDeveloper라는 타입가드를 정의하면 같은 로직을 아래와 같이 사용할 수 있다.

// 타입가드를 정의
function isDeveloper(target:Developerr|Personn):target is Developerr {
    return (target as Developerr).skill !== undefined;
}

if(isDeveloper(tonytony)){
    console.log(tonytony.skill)
}else{
    console.log(tony.age)
}

타입호환

타입 호환이란 타입스크립트 코드에서 특정 타입이 다른 타입에 잘 맞는지를 의미한다. 타입스크립트는 정의되어 있는 속성의 타입에 따라 호환되는지를 확인한다. 이를 구조적 타입시스템이라고 한다.

sum이 add보다 타입구조적으로 더 넓기때문에 sum은 add와 호환이 안됨

인터페이스 - 클래스의 타입호환

interface Named {
    name: string;
}

class Person {
    name: string;
}

let p: Named;
// 성공, 구조적 타이핑이기 때문입니다.
p = new Person();

함수 - 제네릭의 타입호환


📑 referece

'TypeScript' 카테고리의 다른 글

타입스크립트의 모듈  (0) 2021.08.01
class와 generic  (0) 2021.08.01
타입스크립트 - 변수와 함수 타입  (0) 2021.07.13
Why Typescript?  (0) 2021.07.12

프로토타입

자바스크립트는 객체를 상속하기 위해 프로토타입이라는 방식을 사용한다. 자바스크립트는 프로토타입 기반언어로서 모든 객체들이 메서드와 속성들을 상속 받기 위한 템플릿으로 프로토타입 객체(prototype object)를 갖는다. 프로토타입 객체로 또 다시 상위 프로토타입 객체로부터 메서드와 속성을 상속 받을 수도 있고 그 상위 프로토 타입 객체로 마찬가지다. 이를 프로토타입 체인이라고 부르고 다른 객체에 정의된 메서드와 속성을 한 객체에서 사용할 수 있도록 한다.

상속되는 속성과 메서드들은 각 객체가 아니라 객체의 생성자의 prototype이라는 속성에 정의되어 있다. prototype 속성도 하나의 객체이며 프로토타입 체인을 통해 상속하고자 하는 속성과 메서드를 담아주는 버킷으로 주로 사용된다.

객체를 선언했을 때 사용할 수 있는 메서드는 Object라는 최상위 프로토타입 객체를 갖고 있기 때문이다.

클래스

프로토타입 기반의 상속은 유지되고, 문법만 바뀐 것이다.

class Person{
    // 객체를 만들 때 호출됨
    constructor(name, age){
        this.name = name;
        this.age = age;
        console.log('생성되었음')
    }
}

const inkuk = new Person('사람',30);
function Person(name,age){
    this.name = name;
    this.age = age;
}

var capt = new Person('캡틴',100)
class Developer{
    // 변수의 접근 범위를 지정할 수 있다.
    private name:string;
    public age:number;
    readonly log:string;

    constructor(name:string,age:number){
        this.name = name;
        this.age = age;
    }
}

제네릭(Generics)

한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 생성하는데 사용한다. 타입스트립트에서는 타입을 함수의 파라미터처럼 받을 수 있는 것을 제네릭이라고 한다. 함수를 정의할 때가 아닌 호출하는 시점 에 타입을 정의해 파라미터와 반환값에 대한 정확한 타입 추론이 가능하다. 다양한 타입을 받기위해 같은 기능을 하는 함수를 타입만 다르게 여러번 선언할 필요가 없기 때문에 유지보수, 코드 가독성이 좋아진다.

타입을 정의하지 않으면 any타입

string 타입을 제네릭으로 넣으면 string 타입으로 바뀜

기존문법과 제네릭의 차이점

  • any 타입과 달리 제네릭으로 타입을 정의하면 제네릭 타입에 해당하는 메서드 자동완성 기능을 사용할 수 있다.
  • union 타입으로 선언하면 input 값에 대한 에러는 없지만 공통속성에 대한 메서드만 사용할 수 있다.
  • 제네릭을 이용해서 타입을 선언하면 자동완성 등 타입선언의 이점을 누릴 수 있다.

인터페이스에 제네릭 선언하기

아래의 예제에서 Email타입과 ProductNumber 타입은 value와 selected 프로퍼티를 갖지만 value의 타입이 달라 두 개의 타입으로 선언했다. 이 경우 interface에 제네릭을 선언해 이용할 수 있다.

interface Email{value:string; selected:boolean}

const emails:Email[] = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

interface ProductNumber
{value:number;selected:boolean}

const numberOfProducts:ProductNumber[] = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];
interface Dropdown<T>{
  value:T;
  selected:boolean;
}

const obj:Dropdown<string> = {
  value:'abc',
  selected:false
}

제네릭의 타입 제한

  1. 정의된 타입
  2. key of 이용하기
    // 타입제한1. 제네릭으로 받은 타입을 배열로 사용할거야
    function logTextLength(text:T[]):T[]{
    // 배열 메서드를 사용할 수 있음
    console.log(text.length);
    return text;
    }

// 타입제한2. 정의된 타입 이용하기
interface LengthType{
length:number;

}

function logTextLength2(text:T):T{
text.length;
return text;
}

// 타입제한3. key of - 선언한 타입 중 하나를
interface ShopingItem{
name:string;
price:number;
stock:number;
}

function getShoppingItemOption(itemOption:T):T{
return itemOption;
}


📑 referece
-MDN - Object prototypes

'TypeScript' 카테고리의 다른 글

타입스크립트의 모듈  (0) 2021.08.01
타입추론, 타입단언, 타입가드  (0) 2021.08.01
타입스크립트 - 변수와 함수 타입  (0) 2021.07.13
Why Typescript?  (0) 2021.07.12

기본타입

  • 문자열
  • 숫자
  • 배열
  • 튜플
  • 객체
  • boolean
  • null, undefiled
  • | 연산자
// 문자열
const str: string = 'hello';

// 숫자
const num: number = 10;

// 배열
const arr: Array<number> = [1, 2, 3];
const heroes: Array<string> = ['Capt', 'tor'];
const items: number[] = [1, 2, 3];

// 튜플
const tuple: [string, number] = ['haha', 1];

// 객체
const obj: object = {};

const person: { name: string; age: number } = {
  name: 'thor',
  age: 1000
};

// boolean
const show: boolean = true;

// undefined, null
let mightBeUndefined : string|undefined = undefined;
let nullableNumber : number|null = null;

// | 연산자
let color:'red'|'orange'|'yellow' = 'red';
color = 'yellow'; //color = 'green'; 

함수타입

  • 함수 타입은 파라미터와 반환값에 타입을 정의한다.

  • return type이 없으면 void 함수

  • function sum(a: number, b: number):number { return a + b; } sum(10, 20);

  • 파라미터를 제한하는 특성으로 파라미터의 갯수나 타입을 체크한다

  • optional parameter : 파라미터에?를 붙이면 파라미터가 없어도 에러가 나지 않는다.

인터페이스

interface는 클래스 또는 객체 를 위한 타입을 지정 할 때 사용하는 문법

  • 변수를 정의
  • 함수의 인자 정의
  • 함수 구조를 정의
  • 인덱싱 방식을 정의
  • 인터페이스 딕셔너리 패턴
  • 인터페이스 확장(상속)

변수정의 및 함수의 인자를 정의하는 인터페이스

// 인터페이스 정의
interface User{
    age:number;
    name:string;
}

// 변수 정의
var saram1:User = {
    age:33,
    name:'세호'
}

// 함수의 인자 정의
function getUser(user:User){
    console.log(user);
}

getUser(saram1)

함수의 스펙(구조)에 인터페이스 활용

interface SumFunction{
    (a:number,b:number):number;
}

let sum: SumFunction;
sum = function(a,b,){
    return a+b
}

인덱싱 방식을 정의하는 인터페이스

interface StringArray{
    [index:number]:string;
}

const arr:StringArray = ['a','b','c']

// indexing
arr[0] = 'd'

인터페이스 딕셔너리 패턴

interface StringRegexDictionary{
    [key:string]:RegExp // 정규표현식
}

const obj:StringRegexDictionary = {
    sth:/abc/, // 통과
    sss:'abc', // 에러
}

인터페이스 확장

interface Person{
    name:string;
    age:number;
}

interface Developer extends Person{    
    language:string;
}

const me:Developer = {
    name:'Gisele',
    age:30,
    language:'javascript'
}

타입별칭(Type Aliases)

  • 타입 별칭은 특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미한다.
  • string,number와 같은 간단한 타입 뿐 아니라 interface 레벨의 복잡한 타입에도 별칭을 부여할 수 있다.
  • 타입 별칭에 제네릭도 사용할 수 있다.
  • 타입 별칭은 새로운 타입 값을 생성하는 것이 아니라 정의한 타입에 대해 나중에 쉽게 참고할 수 있게 이름을 부여하는 것과 같다.
type Person = {
    name:string;
    age:number;
}

const seho:Person={
    name:'세호',
    age:30
}

Alias와 Interface의 차이점

Inferace Type
확장 🌷 가능 불가능
재할당 가능 불가능
목적 구현 데이터를 담기

좋은 소프트웨어는 확장이 용이해야하기 때문에 type보다는 interface로 선언해서 사용하는 것을 추천

연산자를 이용한 타입정의

Union Type(|)

하나 이상의 타입을 쓰고 싶을 때, | 연산자를 이용해 여러 연산자를 여러 개 연결할 수 있다. (or의 의미)

function logMessage(value:string| number){ // union type
    if(typeof value==='number'){     
        console.log(value.toLocaleString())
    }

    if(typeof value==='string'){
        console.log(value.toLowerCase())
    }

    throw new TypeError('value must be string or number')
}
  • 타입 추론이 되기 때문에 아래와 같이 해당 타입에 대한 자동완성 기능을 이용할 수 있다.

  • interface 두 개를 합쳤을 때, 공통된 속성에만 접근할 수 있다.

Intersection Type(&)

여러 타입을 모두 만족하는 하나의 타이블 의미한다.

Union type와 Intersection type의 차이

  • union type으로 선언했을 경우, 그 중 하나에 해당하는 타입으로 사용이 가능하지만, intersection type의 경우 모든 항목을 만족하는 타입을 사용해야 한다.

Enums

이넘은 특정 값들의 집합을 의미하는 자료형이다.
이넘을 선언하고 별도의 값을 지정하지 않으면 숫자형 이넘으로 0부터 1씩 증가한다.

// 숫자형 이넘
enum Shoes{
    Nike, //0
    Adias, //1
    NewBalance//2
}

const myShoes = Shoes.Nike
console.log(myShoes); // 0

// 문자형 이넘
enum Shoess{
    Nike = '나이키',
    Adias = '아디다스',
    NewBalance = '뉴발란스'
}

const myShoes = Shoess.Nike
console.log(myShoes); //나이키

활용

위와 같이 string type으로 타입을 정의할 경우 yes,no가 아닌 다른 값도 들어와서 예외처리를 할 수 없다. Enum type을 사용하면 지정한 값이 아닌 다른 값에 대해 미리 에러가 발생한다.


📑 referece

'TypeScript' 카테고리의 다른 글

타입스크립트의 모듈  (0) 2021.08.01
타입추론, 타입단언, 타입가드  (0) 2021.08.01
class와 generic  (0) 2021.08.01
Why Typescript?  (0) 2021.07.12

타입스크립트란?

TypeScript는 컴파일-타임 타입 검사자가 있는 JavaScript의 런타임입니다.

  • 타입스크립트는 자바스크립트에 타입 을 부여한 언어다.
  • 정적 타입 검사자 로서 프로그램을 실행시키기 전에 값의 종류를 기반으로 프로그램의 오류를 찾는다.
  • 자바스크립트 코드의 런타임 특성 을 절대 변화시키지 않는다. 타입스크립트의 컴파일러가 코드 검사를 마치면 타입을 삭제해서 결과적으로 '컴파일된' 코드를 만든다. 즉 코드가 한번 컴파일되면, 결과로 나온 일반 JS 코드에는 타입 정보가 없다.
  • TypeScript는 Javascript의 상위 레이어 다. Javascript의 기능을 제공하면서 그 위에 자체 레이어를 추가한다. 자바스크립트는 원시타입(string, number, object, undefined 등)을 가지고 있지만, 전체 코드베이스에 일관되게 할당되었는지는 미리 확인해주지 않는다. 타입스크립트는 이 레이어로서 동작한다.
  • 클래스, 인터페이스, 모듈 등의 강력한 기능을 제공하며, 순수한 객체 지향 코드 를 작성할 수 있다.

장점

에러의 사전 방지

함수, 컴포넌트 등의 타입을 추론할 수 있어 코드를 실행하지 않아도 IDE 상에서 바로 알 수 있다.

코드 가이드 및 자동 완성

자동완성이 굉장히 잘된다. 함수를 사용 할 때 해당 함수가 어떤 파라미터를 필요로 하는지, 그리고 어떤 값을 반환하는지 코드를 따로 열어보지 않아도 알 수 있다.

프로그램 부분 간의 더 명확한 통신

리액트 컴포넌트의 경우 해당 컴포넌트를 사용하게 될 때 props에 무엇을 전달해줘야하는지, JSX를 작성하는 과정에서 바로 알 수 있고, 컴포넌트 내부에서도 자신의 props나 state에 어떤 값이 있는지, redux의 store 안에 어떤 상태가 들어있는지 바로 알 수 있다.

타입스크립트 프로젝트 시작하기

  1. 타입스크립트 파일 생성 및 작성
    .ts 확장자

    // index.ts
    function sum(a: number, b: number): number {
    return a + b;
    }
    
    sum(10, 20);
    
  2. 타입스크립트 설치
    $ npm i typescript -g

  3. 자바스크립트 컴파일
    $ tsc index.ts


타입스크립트 설정 파일 옵션

tsconfig.json

예시

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "noImplicitAny": true // 암시적으로 선언되었는데 any로 추론되면 에러 발생
  }
}

📑 referece

'TypeScript' 카테고리의 다른 글

타입스크립트의 모듈  (0) 2021.08.01
타입추론, 타입단언, 타입가드  (0) 2021.08.01
class와 generic  (0) 2021.08.01
타입스크립트 - 변수와 함수 타입  (0) 2021.07.13

+ Recent posts