타입스크립트: 이넘, 유니온 타입, as, implements

공대적 문과생·2022년 1월 20일
0

지난 편에서 충분히 이해하지 못했던 것들을 추가적으로 공부하고, 핸드북 공부 이어가도록 한다. 혹시 이해가 잘못된 부분이 있으면 댓글로 호되게 꾸짖어 주세요.

타입 단언 (Type assertion)

as, is등을 공부하다가 여기까지 왔는데,

https://radlohead.gitbook.io/typescript-deep-dive/type-system/type-assertion 에 의하면 타입 단언이란,

"프로그래머가 컴파일러에게 내가 너보다 타입에 더 잘 알고 있고, 나의 주장에 대해 의심하지 말라고 하는 것과 같다."

타입 단언은 JS를 TS로 포팅할 때 많이 쓰인다고 한다.

var foo = {};
foo.bar = 123; // error. bar 속성이 존재하지 않음.
foo.bas = 'hello'; // error. bas 속성이 존재하지 않음.

위와 같은 경우 타입 단언을 사용해 해결할 수 있다.

interface Foo {
	bar: number;
	bas: string;
}

var foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';

타입 단언은 두 가지 문법으로 사용할 수 있는데 하나는 위에서 나온 as 타입이고 나머지 하나는 <타입> 변수명 이다. 똑같이 꺽쇠를 사용하는 JSX 에서 문법적으로 모호한 경우가 발생해서, 전자를 권장한다고 한다.

타입 단언을 캐스팅이라고 부르지 않는 이유는, 일반적으로 캐스팅이 런타임시에 실행된다는 암시가 있기 때문이라고 한다. 타입 단언은 오로지 컴파일 단계에 관여한다.

대충 캐스팅이라고 생각하고, 공부를 이어나가도록 한다.

extends, implements 키워드

extends는 클래스의 상속이라고 생각하면 이해가 되었다. 예전에 공부한 것 같기도 하고

https://www.howdy-mj.me/typescript/extends-and-implements/

implements는 알고보니 자바스크립트가 아닌 타입스크립트의 개념이었다. 단순히 타입의 체크를 위해 사용한다. 단순히 대상이 되는 클래스의 요소들이 정확히 재정의되는지 확인만 한다고 한다. 메서드와 속성 모두 재정의할 필요가 있고, 단순히 같은 모양의 클래스를 만드는 것에만 집중한다고 한다.

그러면 새로운 메서드나 속성을 만들 경우 에러를 뿜는지 궁금.

JS, TS 모두 동시에 여러 클래스를 상속하는 다중 상속을 지원하지 않는다고 한다.
-> implements는 가능

더 깊이 들어가면 prototype을 완전히 깨우쳐야 하는 것 같으니 이정도만 알아두자.


핸드북 공부를 이어나감.

이넘 (Enum)

숫자형과 문자형 이넘으로 나뉜다.

숫자형 이넘

enum Direction {
	Up = 1,
	Down,
	Left,
	Right
}

초깃값을 주지 않으면 0부터 시작한다.

const getSomeValue = () => 23;

enum E {
	A = getSomeValue(), 
	B, //error Enum member must have initializer
}

숫자형 이넘의 초기화는 상수로 하는 게 좋다..? 계산된(computed) 값을 첫 멤버에 초기화했다고 해서, 그 다음 멤버가 자동으로 increment 되지 않으므로 초기화 해줘야 한다? 잘 모르겠음 아무튼 위 코드에서 B=1로 초기화해주면 정상 작동함.

참고: https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-runtime

문자형 이넘

enum Direction {
	Up = "UP",
	Down = "DOWN",
	Left = "LEFT",
	Right = "RIGHT",
}

왜인지는 모르겠지만 문자형 이넘의 값은 상수와 같은 취급으로 대문자로 쓰는 것 같다.

복합 이넘 (Heterogeneous Enums)

enum BooleanLikeHeterogeneousEnum {
	No = 0,
	Yes = "YES",
}

되긴 되는데,

런타임 시점에서의 이넘 특징

이넘은 런타임에 실제 객체 형태로 존재한다고 한다.

enum E {X,Y,Z}

function getX(obj: {X: number}) {
	return obj.X;
}

getX(E); // 이넘 E의 X는 숫자이기 때문에 정상동작

컴파일 시점에서의 이넘 특징

이넘이 런타임에서는 실제 객체지만 keyof 를 사용할 때는 keyof typeof를 대신 사용하라고 함. (난 아마 쓸 일 없을듯)

리버스 매핑

숫자형 이넘에만 존재. 이넘의 키(key)로서 값을 얻거나, 값으로 키를 얻을 수 있다.

enum Enum { A }

let a = Enum.A; // key 로 value 획득 
let keyName = Enum[a]; // value 로 key 획득

연산자를 이용한 타입 정의

유니온 타입

function logText(text: string | number) {
	//
}

logText 함수의 text파라미터 에는 문자열, 숫자를 모두 넣을 수 있다.

function getAge (age: any) {
	age.toFixed(); // 에러. age의 타입이 any로 추론되기 때문에 숫자 관련 API에서 코드가 자동완성 되지 않음.
	return.age;
}
function getAge(age: number | string) {
	if (typeof age === 'number') {
		age.toFixed(); // 정상동작
		return age;
	} if (typeof age === 'string') {return age;}
	return new TypeError('age must be number or string');
}

소수점 반올림을 하는 데에 사용되는toFixed()string을 반환한다고 한다.

참고:
https://potensj.tistory.com/122

인터섹션 타입 (Intersection Type)

교차 타입은 여러 타입을 만족하는 하나의 타입을 의미.

interface Person {
	name: string;
	age: number;
}

interface Developer {
	name: string;
	skill: string;
}

type Capt = Person & Developer;

//
{
	name: string;
	skill: string;
	age: number;
}
	

번역된 핸드북에 오류가 있다.

유니온 타입을 쓸 때 주의할 점

interface Person {
	name: string;
	age: number;
}
interface Developer {
	name: string;
	skill: string;
}

function introduce(someone: Person | Developer) {
	someone.name; // 정상동작
	someone.age; // 에러.
	someone.skill; // 에러
}

즉, 이 경우 타입 추론시. 별도의 타입 가드 (is)를 사용하지 않으면, 교차되는 name 속성밖에 사용할 수 없게 된다.

profile
공대적 문과생, 추남적 미남, 여성적 남성, 신사적 변태, 이론적 로맨티시스트, 현실적 이상주의자.

0개의 댓글