Type guard를 사용하면 조건문에서 객체의 타입을 좁혀나갈 수 있다.
/**
* 일반적인 인터페이스 예
*/
interface Foo {
foo: number;
common: string;
}
interface Bar {
bar: number;
common: string;
}
/**
* 사용자 정의 Type Guard!
*/
function isFoo(arg: any): arg is Foo {
return arg.foo !== undefined;
}
/**
* 사용자 정의 Type Guard 사용 예시
*/
function doStuff(arg: Foo | Bar) {
if (isFoo(arg)) {
console.log(arg.foo); // ㅇㅋ
console.log(arg.bar); // Error!
}
else {
console.log(arg.foo); // Error!
console.log(arg.bar); // ㅇㅋ
}
}
doStuff({ foo: 123, common: '123' });
doStuff({ bar: 123, common: '123' });
// Type Guard
if (foo.bar) {
console.log(foo.bar.baz); // ㅇㅋ
const bar = foo.bar;
functionDoingSomeStuff(() => {
console.log(bar.baz); // ㅇㅋ
});
}
TS의 특징중하나
기본적인 타입 정의 부터 복잡한 타입까지 정의 가능
새로운 타입을 정의 할 수 있다
type Text = string;
type Num = number;
type Student = {
name: string;
age: number;
}
const name: Text = 'Fizz';
const student: Student = {
s: 'sa' -> error
}
const student: Student = {
name = 'fizz',
age: 28,
} -> ok
리터럴 타입은 집합 타입의 보다 구체적인 하위 타입이다. 이것이 의미하는 바는 타입 시스템 안에서 "Hello World"는 string이지만, string은 "Hello World"가 아니란 것이다
TypeScript에는 문자열과 숫자, 두 가지 리터럴 타입이 있는데 이를 사용하면 문자열이나 숫자에 정확한 값을 지정할 수 있다.
type Name = 'name';
let name: Name;
name = 'a' -> error
name = 'name' -> ok
-> String Literal Types
정해진 String 만 사용가능
유니온 타입(Union Type)이란 자바스크립트의 OR 연산자(||)와 같이 A이거나 B이다 라는 의미의 타입이다.
type TopChamp = 'Garen' | 'Teemo' | 'Galio'
function attack(topChamp: TopChamp) {
} -> String Literal Types, Union Types
type Level = 1 | 2 | 3;
const level : Level = 2;
-> Number Literal Types, Union Types
type SuccessState = {
response: {
body: string;
}
};
type FailState = {
reason: string;
}
type AttackState = SuccessState | FailState
function attack(champ: string): AttackState {
return {
response: {
body: 'success',
}
}
}
function printAttackState(state: AttackState) {
if ('response' in state) {
console.log(${state.response.body});
} else {
console.log({state.reason};
}
} > 되지만 권장 X 그러면???
번역하자면 구별되는 유니언타입들이다.
인터페이스들이 각 공통된 싱글톤 타입(type)을 갖고, Union 타입의 type guards 를 사용하여 switch 에서 모든 경우의 수를 계산하고 각 인터페이스의 데이터까지 구별할 수 있는 고급 패턴이다.
type SuccessState = {
result: 'success';
response: {
body: string;
}
};
type FailState = {
result: 'fail';
reason: string;
}
type AttackState = SuccessState | FailState
function attack(champ: string): AttackState {
return {
result: 'success'
response: {
body: 'success',
}
}
}
function printAttackState(state: AttackState) {
if (state.result === 'success') {
console.log(${state.response.body});
} else {
console.log({state.reason};
}
}
모든것을 다 합한 성격 &같은 개념
type Student = {
name: string;
score: number;
}
type Developer = {
id: number;
coding: () => void;
}
function develop(person: Student & Developer) {
console.log(person.name, person.id, person.coding) -> 모두가 있는 걸 전달해야함
}
develop({
name: 'a',
score: 1,
id: 2,
coding: () => {},
}) -> ok
JS에는 없다!
TS 자체 제공 타입
이름이 있는 상수들의 집합을 정의할 수 있다. 의도를 문서화 하거나 구분되는 사례 집합을 더 쉽게 만들수 있다. TypeScript는 숫자와 문자열-기반 열거형을 제공한다.
enum Champs {
Garen,
Galio,
Gangplank
};
console.log(Champs.Garen); 0
const topChamp = Champs.Galio;
console.log(topChamp) 1
enum Champs {
Garen = 1,
Galio,
Gangplank
};
console.log(Champs.Garen); 1
const topChamp = Champs.Galio;
console.log(topChamp) 2
enum Champs {
Garen = 'Garen',
Galio = 'Garen',
Gangplank = 'Gangplank',
};
console.log(Champs.Garen); 'Garen'
const topChamp = Champs.Galio;
console.log(topChamp) 'Garen'
하지만 TS에서 Enum은 피하는 것이 좋다.
enum으로 타입이 지정된 변수에 다른 어떠한 숫자도 할당할 수있다. (위에는 타입 추론으로 생략했다)
컴파일 에러가 발생하지 않는다. 즉 타입이 정확하게 보장되지 않는다. 또한 union타입을 활용해 대체 가능하다
type Champs = 'Garen' | 'Galio' | 'Gangplank';
타입 추론이라 한다.
let text = 'hello'; -> 자동으로 string으로 타입추론
//뻔한경우에는 생략해도 추론된다.
text = 1; >> error!
function print(msg) { -> any로 추론되어 warning
//최대한 인자는 명시! 기본값 할당시 타입 추론 다른 타입으로 가능 ex msg = 'ee' -> string
}
function add(x: number, y: number) {
return x + y -> 자동으로 숫자로 추론
}
const result = add(1, 2) ->자동으로 숫자로 추론
좋다고 생각하지 않는다. -> 실제로 간단하게 함수를 작성하지 않음 왠만하면 명시해라. (너무 뻔한거 제외)
보통 style guide로 프로젝트 전 정해야함
타입 표명이라 한다. (피하면 좋다!)
TypeScript에서는 시스템이 추론 및 분석한 타입 내용을 우리가 원하는 대로 얼마든지 바꿀 수 있다. 이때 "타입 표명(type assertion)"이라 불리는 메커니즘이 사용된다.
function a(): any {
return 1;
}
const b = a();
console.log((b as string).length) -> assertion
console.log((<string>b).length) -> assertion
function findNumbers(): number[] | undefined {
return undefined
}
const nubers = findNumbers(); () 뒤에 ! 써도 된다
numbers!.push(2) --> 확신할때 ! 쓴다 ?은 optional
정말 확신할떄는 ! 써도 된다