ㅇㅇㅈ Blog

프론트엔드 수행중

0%

TypeScript-03

작성자와 사용자의 관점으로 코드 바라보기

타입이란 해당 변수가 할 수 있는 일을 결정한다

1
2
3
4
5
6
7
8
9
10
11
12
13
// JavaScript
// f1이라는 함수의 body에서는 a를 사용한다
// a가 할 수 있는 일은 a의 타입이 결정한다
function f1(a){
return a
}

// 사용자는 사용법을 숙지하지 않은 채, 문자열을 사용하여 함수를 실행
function f1(a){
return a * 38
}
console.log(f2(10)) // 380
console.log(f2('Mark')) // NaN

타입스크립트의 추론에 의지하는 경우

1
2
3
4
5
6
7
8
9
10
// 타입스크립트 코드지만
// a의 타입을 명시적으로 지정하지 않은 경우이기 때문에 a는 any로 추론된다
// 함수의 리턴타입은 number로 추론된다(NaN도 number이기 때문에)

function f3(a){
return a * 38
}
// 사용자는 a가 any이기 때문에, 사용법에 맞게 문자열을 사용하여 함수를 실행
console.log(f3(10)) // 380
console.log(f3('Mark')) // NaN

nolmplicitAny 옵션

타입을 명시적으로 지정하지 않은경우, 타입스크립트가 추론 중 ‘any’라고 판단하게 되면,
컴파일 에러를 발생시켜 명시적으로 지정하도록 유도한다

noImplicitAny 에 의한 방어

1
2
3
4
5
6
7
8
9
// error TS7006: Parameter 'a' implicitly has an 'any' type

function f3(a){
return a * 38;
}
// 사용자의 코드를 실행할 수 없습니다. 컴파일이 정상적으로 마무리 될 수 있도록 수정해야 합니다.
console.lof(f3(10))
console.log(f3('Mark') + 5)

number타입으로 추론된 리턴 타입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 매개변수의 타입은 명시적으로 지정
// 명시적으로 지정하지 않은 함수의 리턴 타입은 number로 추론된다

function f4(a: number){
if(a>0){
return a * 38
}
}

// 사용자는 사용법에 맞게 숫자형을 사용하여 함수를 실행했습니다.
// 해당 함수의 리턴 타입은 number이기 때문에, 타입에 따르면 연산을 바로 할 수 있다
// 하지만 실제 undefined + 5가 실행되어 NaN이 출력된다

console.log(f4(5)) // 190
console.log(f4(-5) + 5) // NaN

strictNullChecks 옵션

  • 모든 타입에 자동으로 포함되어 있는 ‘null’과 ‘undefined’를 제거해준다

number | undefined 타입으로 추론된 리턴 타입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 매개변수의 타입은 명시적으로 지정
// 명시적으로 지정하지 않은 함수의 리턴 타입은 number | undefined로 추론

function f4(a: number){
if(a>0){
return a * 38;
}
}

// 사용자는 사용법에 맞게 숫자형을 사용하여 함수를 실행
// 해당 함수의 리턴 타입은 number | undefined 이기 때문에,
// 타입에 따르면 이어진 연산을 바로 할 수 없다
// 컴파일 에러를 고쳐야하기 때문에 사용자와 작성자가 의논을 해야한다

console.log(f4(5))
console.log(f4(-5) + 5) // error TS2532: Object is possibly 'undefined'

명시적으로 리턴타입을 지정해야 할까?

1
2
3
4
5
6
7
8
9
// 매개변수의 타입과 함수의 리턴 타입을 명시적으로 지정했습니다.
// 실제 함수 구현부의 리턴 타입과 명시적으로 지정한 타입이 일치하지 않아 컴파일 에러가 발생한다

// error TS2366
function f5(a: number): number {
if( a > 0){ // if만 리턴 되기 때문에 if가 아닌 부분에 대한 작업이 필요함
return a * 38
}
}
  • noImplicitReturns 옵션을 켜면
    • 함수내에서 모든 코드가 값을 리턴하지 않으면, 컴파일 에러를 발생 시킨다
1
2
3
4
5
6
7
8
// if가 아닌 경우 return을 직접하지 않고 코드가 종료된다

// error TS7030: Not all code paths return a value.
function f5(a: number){
if( a > 0){
return a * 38;
}
}

매개변수에 object가 들어오는 경우

1
2
3
4
5
6
7
8
// JS

function f6(a){
return `이름은 ${a.name}이고, 연령대는 ${Math.floor(a.age / 10) * 10}대 입니다.`
}

console.log(f6({name: 'Mark', age: 38})) // 이름은 Mark이고, 연령대는 30대 입니다
console.log(f6('Mark')) // 이름은 undefined이고, 연령대는 NaN대 입니다

object literal type

1
2
3
4
5
function f7(a: {name: string; age: number}): string {
return `이름은 ${a.name}이고, 연령대는 ${Math.floor(a.age / 10) * 10}대 입니다.`
}
console.log(f7({name:'Mark', age:38})) // 이름은 Mark이고, 연령대는 30대 입니다.
console.log(f7('Mark')) // error TS2345 : Argument of type 'string' is not assignable to parameter of type '{name: string; age: number;}'

매번 이렇게 오브젝트의 타입을 지정해주는건 힘들기 때문에 나만의 타입을 만들 수 있다

나만의 타입을 만드는 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface PersonInterface {
name : string
age : number
}
type PersonTypeAlias = {
name: string;
age: number;
}

function f8(a: PersonInterface): string {
return `이름은 ${a.name}이고, 연령대는 ${Math.floor(a.age/10) * 10}대 입니다.`
}

console.log(f8({name:'Mark', age: 38})) // 이름은 Mark이고, 연령대는 30대 입니다.
console.log(f8('Mark')) // error TS2345: Argument of type 'string' is not assignable to parameter of type 'PersonInterface'

타입스크립트 코드를 작성하는 사람으로서 어떻게 타입을 표현할 수 있는지가 중요