타입 | 예시 | 설명 |
---|---|---|
number | 1, 5.3, -10 | 모든 숫자들, 정수와 실수형 간 차이 없음 |
string | ‘Hi’, “Hi”, `Hi` | 모든 문자 값 |
boolean | true, false | 오직 참과 거짓 두 가지 값 |
object | {age: 30} | 모든 자바스크립트 객체, 객체의 타입 지정을 구체적으로 명시할 수 있음 |
array | [1, 2, 3] | 모든 자바스크립트 배열, 타입은 요소의 타입에 따라 유연하거나 엄격할 수 있음 |
tuple | [1, 2] | 타입스크립트에 의해 추가된 타입: 정해진 길이의 배열 |
enum | enum {NEW, OLD} | 타입스크립트에 의해 추가된 타입: 자동적으로 열거된 전역 상수 식별자 |
any | * | 모든 종류의 값, 타입 배정이 필요하지 않음 |
unknown | * | 모든 종류의 값, any와 유사하지만, unknown 타입에 어떤 것을 대입하는 것이 유효하지 않아 더 안전함 |
function | function a(n1: number, n2: number) : number | 매개변수 타입과 반환 타입 표기가 가능함 |
void | function noop(): void { return; } | 값을 반환하지 않는 함수의 반환 값을 의미함 |
union | number | string |
intersection | Person & Developer | union이 or이라면 intersection은 and, 자주 사용되는 방법은 아님 |
literal | 'as-number' | 'as-text' |
null | null | 명시적으로 빈 값을 나타냄 |
undefined | undefined | 선언 후 아무 값도 할당받지 않은 초기 상태 |
never | function fail(msg: string): never { throw new Error(msg); } | 절대 관측될 수 없는 값을 의미, 함수가 예외를 발생시키거나, 프로그램 실행을 종료함을 의미함 |
function add(n1, n2) {
return n1 + n2;
}
const number1 = '5';
const number2 = 2.8;
const result = add(number1, number2);
console.log(result); // 52.8
위의 예시는 수학적 계산 결과가 아니라 문자열과 숫자가 연결되어 반환된다.
이러한 부분은 에러를 찾기 어렵게 만들고 버그로 이어질 가능성이 있다.
타입스크립트를 사용하면 타입 에러를 개발 단계에서 발견할 수 있다.
타입스크립트는 컴파일을 차단하지 않고 실수를 알려준다.
동일한 이름의 js 파일과 ts 파일을 동시에 열어두면 Duplicate function implementation 오류가 발생하니 주의하자.
타입스크립트 기능은 자바스크립트 엔진에 내장되어 있지 않기 때문에 개발 단계에서만 지원을 받을 수 있다. 그래서 타입스크립트는 브라우저에서 실행할 수 없으며 개발 단계에서 컴파일 할 때만 실행 가능하다.
타입스크립트의 주요 원시 타입은 모두 소문자이다.
let number1: number = 5;
let str = "test";
str = 0; // 에러 발생
const person: {
name: string;
age: number;
}
const product = {
id: 'abc1',
price: 12.99,
tags: ['great-offer', 'hot-and-new'],
details: {
title: 'Red Carpet',
description: 'A great carpet - almost brand-new!'
}
}
{
id: string;
price: number;
tags: string[];
details: {
title: string;
description: string;
}
}
const person = {
name: 'Maximilian',
age: 30,
hobbies: ['Sports', 'Cooking'],
role: [2, 'author']
};
person.role.push('admin');
person.role[1] = 10;
const person: {
name: string;
age: number;
hobbies: string[];
role: [number, string];
} = {
name: "Maximilian",
age: 30,
hobbies: ["Sports", "Cooking"],
role: [2, "author"],
};
person.role.push('admin');
person.role[1] = 10; // 에러 발생
const person = {
name: "Maximilian",
age: 30,
hobbies: ["Sports", "Cooking"],
role: 2,
};
// role 2가 admin 권한인지 read only인지..
const person = {
name: "Maximilian",
age: 30,
hobbies: ["Sports", "Cooking"],
role: 'READ ONLY USER',
};
if(person.role === 'READ-ONLY-USER') {
console.log('is read only');
}
const ADMIN = 0;
const READ_ONLY = 1;
const AUTHOR = 2;
const person = {
name: "Maximilian",
age: 30,
hobbies: ["Sports", "Cooking"],
role: ADMIN,
};
if (person.role === ADMIN) {
console.log("is admin");
}
enum Role { ADMIN, READ_ONLY, AUTHOR };
const person = {
name: "Maximilian",
age: 30,
hobbies: ["Sports", "Cooking"],
role: Role.ADMIN,
};
if (person.role === Role.AUTHOR) {
console.log("is author");
}
var Role;
(function (Role) {
Role[Role["ADMIN"] = 0] = "ADMIN";
Role[Role["READ_ONLY"] = 1] = "READ_ONLY";
Role[Role["AUTHOR"] = 2] = "AUTHOR";
})(Role || (Role = {}));
;
enum Role { ADMIN='admin', READ_ONLY=1, AUTHOR };
// 런타임 검사 예시
if(typeof n1 !== 'number' || typeof n2 !== 'number') {
throw new Error('Incorrect input');
}
function combine(input1: number | string, input2: number | string) { // Union Type
const result = input1 + input2; // Error: Operator '+' cannot be applied to types 'string | number' and 'string | number'.
return result;
}
const combinedAges = combine(30, 26);
console.log(combinedAges);
const combinedNames = combine('Max', 'Anna');
console.log(combinedNames);
function combine(input1: number | string, input2: number | string) {
let result;
if(typeof input1 === 'number' && typeof input2 === 'number') {
result = input1 + input2;
}else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26);
console.log(combinedAges);
const combinedNames = combine('Max', 'Anna');
console.log(combinedNames);
런타임 타입 검사를 추가해 해결할 수 있다.
Union 타입을 사용하면 매개변수를 보다 유연하게 사용할 수 있다.
function combine(
input1: number | string,
input2: number | string,
resultConversion: string
) {
let result;
if (typeof input1 === "number" && typeof input2 === "number" || resultConversion === 'as-number') {
result = +input1 + +input2;
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26, "as-number");
console.log(combinedAges);
const combinedStringAges = combine('30', "26", "as-number");
console.log(combinedStringAges);
const combinedNames = combine("Max", "Anna", "as-text");
console.log(combinedNames);
function combine(
input1: number | string,
input2: number | string,
resultConversion: 'as-number' | 'as-text' // Literal Type
) {
let result;
if (typeof input1 === "number" && typeof input2 === "number" || resultConversion === 'as-number') {
result = +input1 + +input2;
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26, "as-number");
console.log(combinedAges);
const combinedStringAges = combine('30', "26", "as-number");
console.log(combinedStringAges);
const combinedNames = combine("Max", "Anna", "as-text");
console.log(combinedNames);
// Type Alias
type Combinable = number | string;
type ConversionDescriptor = "as-number" | "as-text";
function combine(
input1: Combinable,
input2: Combinable,
resultConversion: ConversionDescriptor
) {
let result;
if (
(typeof input1 === "number" && typeof input2 === "number") ||
resultConversion === "as-number"
) {
result = +input1 + +input2;
} else {
result = input1.toString() + input2.toString();
}
return result;
}
const combinedAges = combine(30, 26, "as-number");
console.log(combinedAges);
const combinedStringAges = combine('30', "26", "as-number");
console.log(combinedStringAges);
const combinedNames = combine("Max", "Anna", "as-text");
console.log(combinedNames);
type User = { name: string; age: number };
const u1: User = { name: 'Max', age: 30 };
type User = { name: string } | string;
let u1: User = {name: 'Max'};
u1 = 'Michael';
function add(n1: number, n2: number): string {
return n1 + n2; // Error!
}
function add(n1: number, n2: number) {
return n1 + n2;
}
function printResult(num: number): void {
console.log('Result: ' + num);
}
printResult(add(5, 12)); // Result: 17
console.log(printResult(add(5, 12))); // undefined
function add(n1: number, n2: number) {
return n1 + n2;
}
function printResult(num: number): undefined { // Error: A function whose declared type is neither 'void' nor 'any' must return a value.
console.log('Result: ' + num);
// return; // return을 추가하면 에러가 발생하지 않음
}
printResult(add(5, 12));
console.log(printResult(add(5, 12))); // undefined
function add(n1: number, n2: number) {
return n1 + n2;
}
let combineValues; // any
combineValues = add;
combineValues = 5; // Runtime Error
console.log(combineValues(8, 8));
function add(n1: number, n2: number) {
return n1 + n2;
}
function printResult(num: number): void {
console.log('Result: ' + num);
}
let combineValues: Function;
combineValues = add;
combineValues = 5; // Compile Time Error
combineValues = printResult; // Runtime Error
console.log(combineValues(8, 8));
let combineValues: (a: number, b: number) => number;
함수 타입을 사용하여 이와 같이 개선할 수 있다.
콜백과 함수 타입은 거의 같은 방식으로 생성된다.
function addAndHandle(n1: number, n2: number, cb: (num: number) => void) {
const result = n1 + n2;
cb(result);
}
addAndHandle(10, 20, (result) => {
console.log(result);
return result; // void라 정의해도 에러가 안남
});
let userInput: unknown; // any일 경우 에러 안 남
let userName: string;
userInput = 5;
userInput = 'Max';
userName = userInput; // Error: Type 'unknown' is not assignable to type 'string'.
let userInput: unknown;
let userName: string;
userInput = 5;
userInput = "Max";
if (typeof userInput === "string") {
userName = userInput;
}
function generateError(message: string, code: number) {
throw { message: message, errorCode: code };
}
const result = generateError("An error occurred!", 500);
console.log(result); // 콘솔에 찍히지 않음
이 글은 Udemy - Typescript :기초부터 실전형 프로젝트까지 with React + NodeJS 강의를 보고 정리한 내용입니다.
잘못된 부분이 있다면 댓글로 피드백 주시면 감사하겠습니다!