앞서 말했듯, typescript 데이터 타입은 한번 지정되면 다른 타입으로 재할당 될 수 없다.
따라서 다음과 같이 편리한 상황이 가능하다.
//js
function add(n1, n2) {
if (typeof n1 !== 'number' || typeof n2 !== 'number') {
throw new Error('Incorrect input!');
}
return n1+n2;
}
//ts
function add(n1: numnber, n2: number) {
return n1+n2;
}
Typescript에는 Javascript에서 동일한 타입을 지원하고, 추가적인 열거 타입이 제공된다.
오브젝트와 레퍼런스 형태가 아닌 실제 값을 저장하는 자료형이다.
primitive type의 내장 함수를 사용 가능한 것은 자바스크립트의 처리 방식 덕분에 가능하다.
리터럴 값으로 primitive 타입의 서브 타입을 나타낼 수 있다.
let isDone: boolean = false;
isDone = true;
console.log(typeof isDone); //boolean
let isOk: Boolean = true;
//래퍼 객체 타입 사용하지 않음
let isNotOk: boolean = new Boolean(true);
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let notANumber: number = NaN;
let underscoreNum: number = 1_000_000;
모든 숫자는 부동 소수점 값이다.
16진수, 10진수, 2진수, 8진수 모두 표현 가능하다.
'string' 형식을 사용한다.
큰 따옴표나 작은 따옴표를 사용한다.
행에 걸쳐 있거나, 표현식을 넣을 수 있는 문자열
백틱 기호에 둘러 쌓여서 ${} 와 함께 사용한다.
let age: number = 39;
let sentence: string = `Hello i am ${ age }.`;
new Symbol
로 사용할 수 없다.
Symbol을 함수로 사용해서 symbol 타입을 만들어낼 수 있다.
console.log(Symbol('foo') === Symbol('foo')); //false
const sym = Symbol(); //고유한 값
const obj = {
[sym]: 'value'
};
obj[sym];
프리미티브 타입의 갑승ㄹ 담아서 사용한다.
고유하고 수정 불가능한 값으로 만들어줘서 주로 접근을 제어하는 데에 사용한다.
실제로 null, undefined 라는 타입을 가진다.
둘 다 소문자만 존재한다.
설정을 하지 않고 이 타입이 할당된 변수에는 null, undefined 라는 값 말고는 할당을 할 수 없다.
tsconfig.json 컴파일 옵션에서 --strictNullChecks
사용하면, null과 undefined 는 void나 자기 자신들에게만 할당할 수 있다.
-> 이 경우 null과 undefined를 할당할 수 있게 하려면, union type을 이용해야한다.
let MyName: number = undefined;
let u: undefined = undefined;
let v: void = undefined;
let v2: void = null;
let union: string | null = null; //가능
null이라는 값으로 할당돼서 무언가가 있는데 사용할 준비가 안된 상태
typeof 연산자를 사용하면 object이다.
값을 할당하지 않은 변수로 무언가가 아예 준비가 안된 상태
typeof 연산자 사용하면 undefined이다.
//리터럴 방식
const p = { name: 'ye', age: 26 };
//create by Object.create
const p2 = Object.create({ name: 'yy', age: 26 });
non-primitive 타입을 나타낼 때 사용하는 타입이다.
자바스크립트에서 array는 객체이다.
let list: number[] = [1, 2, 3];
let list: (number | string)[] = [1, 2, "3"];
let list: Array<number> = [1, 2, 3];
let x: [string, number];
x = ['ye', 33];
const [first, second] = x;
//분해할당
//first는 string, second는 number
function returnAny(msg: any): any {
console.log(msg);
}
const any1 = returnAny("리턴은 아무거나");
any1.toString();
어떤 것이든 할 수 있다. 라는 의미의 타입.
any는 개체를 통해 계속해서 전파된다.
편의 -> 타입 안정성 잃음
let looseTyped: any = {};
const d = looselyTyped.a.b.c.d;
function leakingAny(obj: any) {
const a: number = obj.num; //누수 막기
const b = a+1;
return b;
}
응용 프로그램을 작성할 떄 모르는 변수의 타입을 묘사해야 할 수도 있다.
이러한 값은 동적 콘텐츠의 모든 값을 의도적으로 수락하기를 원할 수 있다.
이 경우 컴파일러와 나중에 코드 읽는 사람에게 이 변수가 무엇이든 될 수 있음을 알려주는 타입을 제공한다. (unknown)
declare const maybe: unknown;
//타입 시스템이 도와줌
if (maybe === true) { //maybe는 boolean 타입 됨
const aBoolean: boolean = maybe;
}
if (typeof maybe === "string") { //maybe가 string이 됨
cont aString: string = maybe;
}
any보다 type-safe한 타입이다.
any와 같이 아무거나 할당 가능하다.
컴파일러가 타입을 추론할 수 있게끔 타입의 유형을 좁히거나 타입을 확정해주지 않으면 다른 곳에 할당하거나 사용할 수 없다.
function error(msg: stirng): never {
throw new Error(msg);
}
function fail() {
return error('failed');
}
funciton infiniteLoop(): never {
while(true) {}
}
모든 타입의 서브 타입이며 모든 타입에 할당 할 수 있다.
하지만 never에는 그 어떤 것도 할당할 수 없다. any도
잘못된 타입을 넣는 실수를 막고자 할 때 사용하기도 한다.
let a: string = 'hello';
if (typeof a !== 'string') {
a; //never
}
declare const a: string|number;
if (typeof a !== 'string') {
a; //number
}
어떤 값도 가지지 않은 타입.
function returnVoid(msg: string): void {
console.log(msg);
return; //위에 :void를 명시해준 것은 아무것도 리턴하지 않겠다는 의미
//return undefined까지 된다.
}