Type

정의

타입은 value가 가진 다양한 속성,메서드를 지칭하는 지름길이라고 볼 수 있다.

함수로서의 타입, 클래스로서의 타입 등등 이 있다.

variable(변수) : string, number, boolean, null, undefined, object, function, array 등등..

“red” 를 보면

  1. string 이다.
  2. string이 가진 모든 개체와 method들 이다.

두 방법으로 대답할 수 있다. 예를 들어, string은 charAt(), indexOf() 등 다양한 method를 가진다. 이걸 매번 다 설명하지 않고 모두를 통칭하기 위한 것이 Type 이다.

따라서 Type은 하나의 값이 가지는 다양한 속성과 메소드를 지칭하기 위한 지름길인 것이다.

Typescript에서 모든 값은 type을 가진다.

종류

Primitive Types

기본적인 것들(number, string, null, 등등)

Object Types

내가 만들거나 내장된 것(functions,arrays,classes,objects 등)

Object Types 를 통해 하나의 값이 다른 유형을 지니는 것처럼 속일 수 있다.

Type을 통해

  • 컴파일러는 코드의 오류를 잡아낸다.
  • 다른 사람이 내 코드에 어떤 값들이 나타날지 이해할 수 있다.

예시

1
2
3
4
5
6
7
8
9
10
11
12
const today = new Date();
today.getMonth(); // today. 을 입력하면 Date의 method들이 자동완성에 뜬다.

const person = {
    age: 20 // person에 마우스 커서를 올려보면 age에 number로 type이 자동 부여된다
};

class Color {

}
const red = new Color();
red. // 이렇게 입력하면 자동완성도 뜨지 않고, 오류가 발생한다. 메서드가 없으니까.

Type annotation and inference

Type annotations

TS에게 변수가 어떤 유형의 값을 나타내는지 말해주기 위한 우리가 작성하는 코드

Type inference : TS가 변수가 어떤 유형의 값을 나타내는지 파악하려하는 것

const : 변수 지정

let : 후에 변수 재지정 가능

Type annotation 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
let apples: number = 5;
let speed: string = 'fast';
let hasName: boolean = true;

let nothingMuch: null = null;
let nothing: undefined = undefined;

// built in objects
let now: Date = new Date();

// Array, 왼쪽에 타입을 적어서 내부 원소의 타입 지정
let colors: string[] = ['red', 'green', 'blue'];
let myNumbers: number[] = [1, 2, 3];
let truths: boolean[] = [true, true, false];

// Classes, 첫 글자만 대문자인 것은 일반적으로 클래스 이름을 나타낸다.
class Car {}
let car: Car = new Car();

// Object literal, 세미콜론(;)으로 분리해야한다.
let point: { x: number; y: number } = {
  x: 10,
  y: 20,
};

// Function, : 부분이 annotation 이고 '=' 이후로 함수가 시작된다.
const logNumber: (i: number) => void = (i) => {
  console.log(i);
};

Type inference

const color = ‘red’; 는 두 부분으로 나뉜다.

const color : Variable Declaration

'red'; : Variable Initialization

let apples: number =5 ; 로 선언 후

apples에 커서를 가져다대면 number가 type으로 뜬다.

let apples = 5; 로 수정해도 똑같이 뜬다. 이것이 type inference

Type annotations 사용하는 경우

함수가 ‘any’ 타입을 반환하여 값을 명확히 하고싶을 때

1
2
3
4
5
6
7
8
// when to use annotations
// 1) Function that returns the 'any' type
const json = '{"x": 10, "y": 20}';
const coordinates = JSON.parse(json); // coordinate : any로 뜬다.
console.log(coordinates); // {x: 10, y:20};

// 수정 후
const coordinates: { x: number; y: number } = JSON.parse(json); // coordinate의 type을 알수있다.
  • TS에서 JSON.parse 는 항상 any타입을 반환한다.

  • any 타입은 TS가 정확한 타입을 모른다는 것을 의미하다.
  • any타입에 대해선 TS가 오류를 잡아낼 수 없기 떄문 최대한 지양해야 한다.

변수를 선언하고 나중에 초기화할 때

1
2
3
4
5
6
7
8
9
10
11
12
13
// 2) when we declare a variable on one line
// and initalizate it later
let words = ['red', 'green', 'blue'];
let foundWord; // fondWord는 any 타입

for (let i = 0; i < words.length; i++) {
  if (words[i] === 'green') {
    foundWord = true;
  }
}

// 수정 후 : 타입을 선언해준다.
let foundWord: boolean;

inference 될 수 없는 타입의 변수를 사용할 때

1
2
3
4
5
6
7
8
9
10
11
12
// 3) Variable whose type cannot be inferred correctly
let numbers = [-10, -1, 12];
let numberAboveZero: boolean = false; // false였다가, 0 이하의 수가 나타나면 그 수가 되는 변수

for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] > 0) {
    numberAboveZero = numbers[i]; // boolean으로 선언했기 떄문에 숫자로 설정할 수 없다.
  }
}

// 수정 후 : boolean 혹은 number로 설정
let numberAboveZero: boolean | number = false;

Type annotation for Function : 함수가 어떤 타입의 인수를 받고 어떤 타입의 값을 반환하는지 작성

1
2
3
const logNumber: (i: number) => void = (i: number) => {
  console.log(i);
};

Type inference for functions : 함수가 어떤 타입의 값을 반환하는지 파악

1
2
3
4
5
const add = (a: number, b: number): number => {
  // 오류가 발생한다. number 타입을 반환하지 않고 있기 떄문
  // 아래 코드를 작성하면 오류가 고쳐진다. 위에서 말한대로 number를 반환하기 때문
  // return a + b;
};

TS는 올바른 Type에 대해 판단할 뿐, Logic은 판단하지 않는다.

1
2
3
4
5
6
7
const subtract = (a: number, b: number) => {
  a - b; // return을 하지 않아 void type을 반환한다. annotation을 안했기 때문에 TS는 오류를 발견하지 못한다.
};

const subtract = (a: number, b: number): number => {
  a - b; // 함수가 number를 반환한다고 했지만 void를 반환하므로 오류가 감지된다.
};

annotation을 통해 TS가 올바르게 반환하는 함수인지 감지하도록 할 수 있다.

Type inference보단 annoation 사용하자

함수의 반환값 annotation 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// void : return하지 않는 함수. null 이나 undefined를 반환해도 된다.
const logger = (message: string): void => {
  console.log(message);
};

// never : 함수가 끝까지 도달하지 않음. void로 해도 된다.
const throwError = (message: string): never => {
  throw new Error(message);
};

// 에러 메시지 출력 코드 예시
const throwError = (message: string): string => {
  if (!message) {
    throw new Error(message);
  }
  return message;
};

// Object destructuring(구조분해)
const todaysWeather = {
  date: new Date(),
  weather: 'sunny',
};

const logWeather = (forecast: { date: Date; weather: string }): void => {
  console.log(forecast.date);
  console.log(forecast.weather);
};

// destructuring 후 코드
const logWeather = ({
  date,
  weather,
}: {
  date: Date;
  weather: string;
}): void => {
  console.log(date);
  console.log(weather);
};

logWeather(todaysWeather);

// Destructuring
const profile = {
  name: 'alex',
  age: 20,
  coords: {
    lat: 0,
    lng: 15,
  },
  setAge(age: number): void {
    this.age = age;
  },
};

const { age, name }: { age: number; name: string } = profile;
const {
  coords: { lat, lng },
}: { coords: { lat: number; lng: number } } = profile;