TS 2일차

Fizz·2022년 9월 25일
0

Type Guard

Type guard를 사용하면 조건문에서 객체의 타입을 좁혀나갈 수 있다.

  • typeof
  • instanceof
  • in
  • 리터럴 Type Guard ( 리터럴 값의 경우 === / == / !== / != 연산자를 사용해 타입을 구분할 수 있다)
  • null과 undefined (strictNullChecks)
    TypeScript는 a == null / != null로 null과 undefined 모두 걸러낸다
  • 사용자 정의 Type Guards
/**
 * 일반적인 인터페이스 예
 */
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와 Callback
    TypeScript는 콜백 함수 내에서 type guard가 계속 유효하다고 여기지 않는다. 해결법은 로컬 변수를 선언하고 그 안에 값을 담아 타입 추론이 가능하도록 만드는 것이다.
// Type Guard
if (foo.bar) {
  console.log(foo.bar.baz); // ㅇㅋ
  const bar = foo.bar;
  functionDoingSomeStuff(() => {
  console.log(bar.baz); // ㅇㅋ
  });
}

Type Alias

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

Literal Types

리터럴 타입은 집합 타입의 보다 구체적인 하위 타입이다. 이것이 의미하는 바는 타입 시스템 안에서 "Hello World"는 string이지만, string은 "Hello World"가 아니란 것이다

TypeScript에는 문자열과 숫자, 두 가지 리터럴 타입이 있는데 이를 사용하면 문자열이나 숫자에 정확한 값을 지정할 수 있다.

String Literal Types

type Name = 'name';
let name: Name;
name = 'a' -> error
name = 'name' -> ok

-> String Literal Types
정해진 String 만 사용가능

Union Types: OR

유니온 타입(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

example

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 그러면???

Discriminated Union

번역하자면 구별되는 유니언타입들이다.

인터페이스들이 각 공통된 싱글톤 타입(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};
    }
}

intersection type

모든것을 다 합한 성격 &같은 개념

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

Enum

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';

Type inference

타입 추론이라 한다.

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로 프로젝트 전 정해야함

Type Assertion

타입 표명이라 한다. (피하면 좋다!)
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
정말 확신할떄는 ! 써도 된다
profile
성장하고싶은 개발자

0개의 댓글