변수의 타입을 지정하고 싶을 때는 변수명 뒤에 콜론을 표시한 뒤 타입을 입력한다.
let 변수명: 타입;
정수(int), 실수(float) 구분없이 모두 number로 표시한다.
let age: number = 20;
문자열을 나타낸다.
let name: string = 'seung';
참과 거짓 값을 나타낸다.
let isAdult: boolean = true;
Symbol은 고유하고 수정불가능한 값으로 만들어줌
주로 접근 제어하는데 쓰는 경우가 많았음
const sym = Symbol();
const obj = {
[sym]: "value",
};
obj[sym];
primitive type 이 아닌 것을 나타내고 싶을 때 사용하는 타입
→ not number, string, boolean, bigint, symbol, null or undefined
let obj: object = {};
obj = { name: 'Mark' };
obj = [{ name: 'Mark' }];
Array<타입>
또는 타입[]
형태로 사용한다.
Array<타입>
형태는 jsf나 tsx에서 충돌이 날 수 있으니 사용을 자제
const list: number[] = [1, 2, 3];
const list2: Array<number> = [1, 2, 3];
배열과 유사하지만 타입과 길이가 고정되어 있다는 점이 다르다.
let tuple: [number, string];
tuple = [1, 'a'];
순서대로 지정된 타입을 입력하지 않으면 에러 발생한다.
tuple = ['b', 3]; // 💥 ERROR
고정된 길이의 배열이지만 push가 가능하긴 하다.
tuple.push('c'); // tuple = [2, 'a', 'c']
enum Role { ADMIN, READ_ONLY, AUTHOR }
어떠한 값이든 들어올 수 있고, any는 최대한 사용하지 않는 것을 권장한다.
왜냐하면 컴파일 타임에 타입 체크가 정상적으로 이루어지지 않기 때문이다.
function returnAny(message): any {
console.log(message);
}
nolmplicitAny 옵션
아무 값이나 지정할 수 있다는 점은 any와 유사하다.
차이점은 any타입을 제외한 다른 타입으로 선언한 변수에 할당할 수 없어서 타입을 먼저 확인한 후에 작업을 할 수 있다.
→ 컴파일러가 타입을 추론할 수 있게끔 타입의 유형을 좁힘
→ 타입을 확정해주지 않으면 다른 곳에 할당할 수 없고, 사용할 수 없음
let userInput: unknown;
let userName: string;
userInput = 5;
userInput = 'Seung';
// userName = userInput; // 💥 ERROR. userInput의 타입을 정확히 체크해야 함.
if (typeof userInput === 'string') {
userName = userInput;
}
값을 반환하지 않는 함수를 사용하는 경우 void를 표준으로 사용한다.
함수가 의도적으로 아무것도 반환하지 않는다면 void 사용해야 한다.
function printResult(str: string): void {
console.log(`Result: ${str}`);
}
위의 printResult 함수와 마찬가지로 아무것도 반환하지 않는 것처럼 유사하다고 생각하겠지만,
return; 을 해줌으로써 반환타입도 undefined가 된다.
function getUndefined(str: string): undefined {
console.log(`Result: ${str}`);
return;
}
strictNullChecks 옵션
해당 변수가 Function 타입이라고 지정할 수 있다.
function add(n1: number, n2: number): number {
return n1 + n2;
}
let combineValues: Function;
combineValues = add;
// combineValues = 5; // 💥 ERROR. 타입이 Function이 아님
combineValues = printResult; // 지정은 되지만 내가 원하는 함수가 아님
하지만, 다른 함수를 지정해도 타입이 Function이기 때문에 변수에 할당이 되는 단점이 있다.
그 점을 해결하기 위해서 화살표함수를 이용해 매개변수 및 반환 타입을 지정해준다.
let combineValues: (a: number, b: number) => number;
combineValues = add;
// combineValues = printResult; // 💥 ERROR. 타입이 맞지 않음
strictFunctionTypes 옵션
class Person() {}
class Developer extends Person {
coding() {};
}
<class StartupDeveloper extends Developer {
burning() {};
}
function tellme(f: (d: Developer) => Developer) {}
function tellme(function dToD(d: Developer): Developer) {
return new Developer();
});
function tellme(function pToD(d: Person): Developer) {
return new Developer();
});
// 💥 StartupDeveloper가 Developer보다 하위 클래스이므로 논리에 맞지 않다.
// → strictFunctionTypes 옵션을 켜주면 에러 발생 시킨다.
function tellme(function dToD(d: StartupDeveloper): Developer) {
return new Developer();
});
에러 발생시키는 함수처럼 아무것도 반환하지 않고 기본적으로 스크립트나 스크립트의 일부를 충돌시키거나 망가뜨리기 위한 함수의 반환값으로 사용가능하다.
never는 모든 타입에 할당할 수 있지만, never에는 그 어떤 것도 할당할 수 없다.
any 조차도 never에게 할당할 수 없다.
그래서 잘못된 타입을 넣는 실수를 막고자 할 때 사용하기도 한다.
function generateError(message: string, code: number): never {
throw { message: message, errorCode: code };
}
generateError('An error occurred!', 500);
2개 이상의 타입을 허용하는 경우이며, | (vertical bar)
를 이용해 타입을 구분한다.
function combine(
input1: number | string
input2: number | string
) {
// ...생략
}
특정한 값을 지정하여 해당 값만 허용하도록 한다.
string뿐만 아니라 number 등 다른 타입들 가능.
function combine(
input1: number | string,
input2: number | string,
// 'as-number' 또는 'as-text'라고 명시된 문자열만 입력가능
resultConversion: 'as-number' | 'as-text'
) {
// ...생략
}
사용자가 타입을 변수로 저장하여 사용할 수 있다.
type Combinable = number | string;
// 'as-number' 또는 'as-text'라고 명시된 문자열만 입력가능
type ConversionDescription = 'as-number' | 'as-text';
function combine(
input1: Combinable,
input2: Combinable,
resultConversion: ConversionDescription
) {
// ...생략
}
type User = { name: string; age: number };
function greet(user: User) {
console.log('Hi, I am ' + user.name);
}
함수의 매개변수 지정한 괄호 뒤에 : 타입명
을 입력하여 지정할 수 있다.
function add(num1: number, num2: number): number {
return num1 + num2;
}
콜백 함수의 매개변수 및 반환 타입도 지정할 수 있다.
콜백 함수는 자신이 전달되는 인수가 반환 값을 기대하지 않는 경우에도 값을 반환할 수 있다.
function sendRequest(data: string, cb: (response: any) => void) {
// ... sending a request with "data"
return cb({data: 'Hi there!'});
}
sendRequest('Send this!', (response) => {
console.log(response);
return true; // ❗️ 반환값은 void이지만 return 가능
});
여러 타입을 합쳐서 사용하는 타입으로, &
를 통해 타입을 결합할 수 있다.
👉 예제 1
아래 예제는 객체를 결합하여 두 타입에 있는 모든 프로퍼티를 사용해야 한다.
type Admin = {
name: string;
privileges: string[];
};
type Employee = {
name: string;
startDate: Date;
};
type ElevatedEmployee = Admin & Employee;
const e1: ElevatedEmployee = {
name: 'seung',
privileges: ['create-server'],
startDate: new Date();
}
👉 예제 2
위의 예제와 다르게 union type으로 이루어진 두 타입을 결합했을 때는 공통의 타입만 사용 가능하다.
type Combinable = string | number;
type Numeric = number | boolean;
type Universal = Combinable & Numeric; // ❗️ number 타입만 가능
런타임 시 특정 타입으로 작업을 수행하기 전에 해당 타입을 검사하는 코드 패턴
여러 타입을 가지는 유니온 타입일 때, 특정 타입일 시 조건을 두는 라인을 타입 가드라고 한다.
👉 예제 1
단순 타입일 때는 typeof
를 통해 확인한다.
function add(a: Combinable, b: Combinable) {
if (typeof a === 'string' || typeof b === 'string') {
return a.toString() + b.toString();
}
return a + b;
}
👉 예제 2
객체 타입의 속성에 접근하는 타입 가드는 in
을 통해 해당 속성 유무를 확인 가능하다.
type UnknownEmployee = Employee | Admin;
function printEmployeeInformation(emp: UnknownEmployee) {
console.log(`Name: ${emp.name}`);
if ('privileges' in emp) {
console.log(`Privileges: ${emp.privileges}`);
}
if ('startDate' in emp) {
console.log(`Privileges: ${emp.startDate}`);
}
}
👉 예제 3
클래스 타입은 instaceof
를 통해 확인한다.
class Car {
drive() {
console.log('Driving...');
}
}
class Truck {
drive() {
console.log('Driving a truck...');
}
loadCargo(amount: number) {
console.log(`Loading cargo... ${amount}`);
}
}
type Vehicle = Car | Truck;
function useVehicle(vehicle: Vehicle) {
vehicle.drive();
if (vehicle instanceof Truck) {
vehicle.loadCargo(1000);
}
}
👉 예제 4
인터페이스 타입은 type 프로퍼티
를 추가해 switch문
으로 구분하는 방법을 사용할 수 있다.
interface Bird {
type: 'bird';
flyingSpeed: number;
}
interface Horse {
type: 'horse';
runningSpeed: number;
}
type Animal = Bird | Horse;
function moveAnimal(animal: Animal) {
let speed;
switch (animal.type) {
case 'bird':
speed = animal.flyingSpeed;
break;
case 'horse':
speed = animal.runningSpeed;
}
console.log(`Moving at speed: ${speed}`);
}
타입스크립트에 특정 값이 특정 타입이라고 알릴 때 유용
<타입명>
을 적어 요소 앞에 추가한다.
const userInputEl = <HTMLInputElement>document.querySelector('#user-input');
userInputEl.value = 'Hi there';
! as 타입명
을 요소 뒤에 추가한다.
const userInputEl = document.querySelector('#user-input')! as HTMLInputElement;
userInputEl.value = 'Hi there';
유연성을 제공하기 위해 프로퍼티 이름과 필요한 프로퍼티의 개수를 지정할 필요가 없다.
프로퍼티 식별자에 []
를 감싸서 프로퍼티 식별자 이름의 타입을 지정한다 ⇒ 지정 타입 내 아무이름이나 가능
❗️ 프로퍼티 식별자 이름의 타입은 boolean 사용 X
interface ErrorContainer {
// id: number; // 💥 인덱스 타입으로 모든 프로퍼티를 string으로 지정했기 때문에 불가능
[prop: string]: string;
}
const errorBag: ErrorContainer = {
email: 'Not a vaild email',
username: 'Must start with a capital character!',
1995: 'number test', // ✨ 프로퍼티 식별자에 숫자를 입력하도 문자열로 해석됨 => '1995'
};
자체적으로 반환 타입을 정확히 추론하지 못하는 경우에 유용하다.
함수 선언 코드 위에 매개변수 및 반환타입을 다르게 지정하여 적어준다.
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: Combinable, b: Combinable) {
if (typeof a === 'string' || typeof b === 'string') {
return a.toString() + b.toString();
}
return a + b;
}
const result = add('kim', ' seung won');
// ❗️ 매개변수 타입이 Combinable일 때는 반환값이 number | string 이므로
// string만 쓸 수 있는 split() 함수 사용 못함
result.split(' ');
정의되어 있는지 여부가 확실하지 않은 요소 다음에 ?
를 추가한다.
❗️ 타입스크립트 3.7 버전 이상에서만 지원
❗️ IDE에서는 컴파일 에러가 뜨지만 구문은 지원함
const fetchedUserData = {
id: 'u1',
name: 'Max',
// job: { title: 'CEO', description: 'My own company' },
};
console.log(fetchedUserData?.job?.title);
null 또는 undefined일 때만 ??
뒤의 값을 할당한다.
❗️ 빈 문자열(’’)이나 0은 앞의 값을 할당
const storedData = userInput ?? 'DEFAULT';