TypeScript

  • 타입스크립트는 자바스크립트 처럼 생겼고 컴파일 했을 때 자바스크립트로 컴파일된다.

  • 자바스크립트는 엄격한 규칙이 없고 사용하기 쉬우며 우리가 원하는 방향으로 수정하기 때문에 인기가 많은데 큰 프로젝트를 하거나 팀으로 일하거나 버그를 최소화하고 싶을 경우에는 단점이 될 수 있다.

  • 타입스크립트는 이러한 단점을 보완하며 언어가 예측 가능하고 읽기 쉬운 코드 등 자바스크립트를 더 잘 사용할 수 있게 한다.

  • 타입스크립트는 typed 언어로 어떤 종류의 변수와 데이터인지 설정해줘야 한다.

  • 만약 해당 타입에 맞지 않게 설정하면 에디터 상에서 오류가 나타나게 된다.

const message: string = "hello world";
console.log(message);

let count = 0;
count += 1;
//다음은 에러가 난다
count = "문자열";

const message: string = "hello world";

const done: boolean = true;

const numbers: number[] = [1, 2, 3]; // 숫자 배열
const message: string[] = ["hello", "world"]; //문자 배열

message.push(1); //숫자는 안된다.

let mightBeUndefined: string | undefined = undefined; //string일수도 잇고 undefined 일수도 있다
let nullableNumber: number | null = null; // number일수도 null일수도 있다

let color: "red" | "orange" | "yellow" = "red"; //red, orange, yello중 하나이다.
color = "yello";
color = "green"; // 에러 발생
  • 특정 변수 또는 상수의 타입을 지정할 수 있고 사전에 지정한 타입이 아닌 값이 설정될 때 바로 에러를 발생시키며 그때는 컴파일이 되지 않는다.

함수에서 타입 정의하기

function sum(x:number, y:number): numver{
  return x+y;  
}

sum(1,2);
  • 타입 스크립트를 사용하면 코드를 작성하는 과정에서 함수의 파라미터로 어떠 타입을 넣어야 하는지 바로 알 수 있다.

  • 가장 우측의 : number 는 해당 함수의 결과물이 숫자라는것을 명시하는 것이다. 이 상태에서 결과물이 number가 아닌 null을 반환한다면 오류가 뜨게된다.


function sumArray(numbers:number[]):number{
  return numbers.reduce((acc, current)=>acc_currend, 0)
}

const total=sumArray({1,2,3,4,5});
  • 타입스크립트를 사용하면 배열의 내장함수를 사용할 때에도 타입 유추가 매우 잘 이루어진다.

  • 함수에서 만약 아무것도 반환하지 않아야 한다면 반환 타입을 void 로 설정하면 된다.

function returnNothing(): void {
  console.log('I am just saying hello world');
}

interface

  • interface는 클래스 또는 객체를 위한 타입을 지정할 때 사용되는 문법이다.
interface Shape {
  getArea(): number; // Shape interface 에는 getArea 라는 함수가 꼭 있어야 하며 해당 함수의 반환값은 숫자이다.
}

class Circle implements Shape {
  //implements 키워드를 사용하여 해당 클래스가 Shape interface의 조건을 충족하겠다는 것을 명시한다

  radius: number; //멤버변수 radius 값을 설정한다.

  constructor(radius: number) {
    this.radius = radius;
  }

  getArea() {
    return this.radius * this.radius * Math.PI;
  }
}

class Rectangle implements Shape {
  width: number;
  height: number;
  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }

  getArea() {
    return this.width + this.height;
  }
}

const shapes: Shape[] = [new Circle(5), new Rectangle(10, 5)];

shapes.forEach((shape) => {
  console.log(shape.getArea());
});
  • 멤버 변수를 선언한 다음에 constructor에서 해당 값들을 하나하나 설정해주었는데 타입스크립트에서는 constructor의 파라미터쪽에 public이나 private accessor를 사용하면 하나하나 설정 해주는 작업을 생략할 수 있다.
class Rectangle implements Shape {
  constructor(private width: number, private height: number) {
    this.width = width;
    this.height = height;
  }
  getArea() {
    return this.width * this.height;
  }
}
  • public으로 선언된 값은 클래스 외부에서 조회할 수 있으며 private으로 선언된 값은 클래스 내부에서만 조회할 수 있다.

일반 객체를 interface로 타입 설정하기

interface Person {
  name: string;
  age?: number; //물음표는 설정해도 되고 안해도 되는 값이라는 의미이다.
}

interface Developer {
  name: string;
  age?: number;
  skills: string[];
}

const person: Person = {
  name: "김사람",
  age: 20,
};

const expert: Developer = {
  name: "김개발",
  skills: ["javascript", "react"],
};

const people: Person[] = [person, expert];
  • Person과 Developer처럼 형태가 유사한 interface를 선언할 때는 다른 interface를 extends 키워드를 사용해서 상속받을 수 있다.
interface Person {
  name: string;
  age?: number; 
}

interface Developer extends Person {
  skills: string[];
}

Type Alias

  • type은 특정 타입에 별칭을 붙이는 용도로 사용하며 객체를 위한 타입을 설정할 수 도 있고, 배열 또는 그 어떤 타입이던 별칭을 지어줄 수 있다.
type Person={
  name: string;
  age?:number;
}

//& 은 Intersction으로 두개 이상의 타입을 합쳐준다.
https://www.typescriptlang.org/docs/handbook/advanced-types.html#intersection-types
type Developer=Person &{
  skills:string[];
}

const person: Person={
  name:"김사람"
}

const expert: Developer{
  name:"김개발",
  skills:["javascript", "react"]
};

type People=Person[];//// Person[] 를 이제 앞으로 People 이라는 타입으로 사용 할 수 있다.
const people:People=[person, expert];

type Color ="red" | "orange" | "yellow";
const color:Color="red";
const colors:Color[]=["red", "orange"]
  • 클래스와 관련된 타입의 경우엔 interface를 사용하는 것이 좋고, 일반 객체의 타입의 경우엔 그냥 type을 사용해도 무방하다.

  • 객체를 위한 타입을 정의할 때 무엇이든 써도 상관 없지만 일관성 있게 사용하도록 한다.

Generics

  • 함수, 클래스, interface, type alias를 사용하게 될 때 여러 종류의 타입에 대하여 호환을 맞춰야 하는 상황에서 사용하는 문법이다.

함수에서 사용하기

  • 객체 A와 객체 B를 합쳐주는 merge라는 함수를 만든다고 할 때 A 와 B가 어떤 타입이 올 지 모르기 때문에 이런 상황에서는 any라는 타입을 쓸 수도 있다.
function merge(a: any, b: any): any {
  return {
    ...a,
    ...b,
  };
}

const merged = merge({ foo: 1 }, { bar: 1 });
  • 그렇지만 이렇게 하면 타입 유추가 모든 깨진것이니 이때는 Generic를 사용한다.

function merge<A, B>(a: A, b: B): A & B {
  return {
    ...a,
    ...b,
  };
}
function wrap<T>(param:T){
  return {
    param
  }
}

const wrapped=wrap(10)
  • 함수에서 Generics를 사용하면 파라미터로 다양한 타입을 넣을 수도 있고 타입 지원을 지켜낼 수 있다.

interface에서 Generics 사용하기

interface Items<T>{
  list:T[;]
}

const items:Items<string>={
  list:["a", "b", "c"]
}

type에서 Generics 사용하기

type Items<T>{
  list:T[];
}

const items: Items<string>={
  list:["a", "b", "c"]
}

클래스에서 Generics 사용하기

  • Queue는 데이터를 등록할 수 있는 자료형이며 먼저 등록(enqueue)한 항목을 먼저 뽑아올 수 (dequeue)있는 성질을 가지고 있다.
class Queue<T> {
  list: T[] = [];
  get length() {
    return this.list.length;
  }
  enqueue(item: T) {
    this.list.push(item);
  }
  dequeue() {
    return this.list.shift();
  }
}

const queue = new Queue<number>()

벨로퍼트와 함께하는 모던 리액트 Interface vs Type alias in TypeScript 2.7 TypeScript에서 Type을 기술하는 두 가지 방법, Interface와 Type Alias React Typescript Tutorial Creating a Todo List App in React using Typescript (Part 1) React With Typescript Crash Course - How To Use React With Typescript Total React Tutorial - For Beginners - Using TypeScript Use TypeScript with React Components React with TypeScript: Best Practices 10++ TypeScript Pro tips/patterns with (or without) React Styled-component #3 with typescript [TypeScript] Advanced Types(고급 타입) Working with React context providers in Typescript How to use React useRef with TypeScript