Typescript
- 타입스크립트(Typescript)는 자바스크립트를 기반으로 정적 타입 문법을 추가한 프로그래밍 언어.
- 타입스크립트를 사용하여 컴파일 시점에 에러를 확인할 수 있음
1. 타입 애너테이션 기초
아래와 같은 형태로 타입을 명시한다. 그 외의 다른 타입의 값을 할당할 때 에러 발생
let myVar: type = value
// 문자열 타입 string
let movieTitle: string = "Apple";
movieTitle = "Pie";
//movieTitle = 9; // error
movieTitle.toUpperCase();
// 숫자 타입 number
let numCatLives: number = 9;
numCatLives += 1;
//numCatLives = "zero" //error
// 불린 타입 boolean
let gameOver: boolean = false;
gameOver = true;
//the any type 모든 타입 가능
let thing: any = "hello";
thing = 1;
thing = false;
thing();
thing.toUpperCase();
2. 함수
//파라미터가 여러 개 가질때 애너테이션 개별로 정할 수 있음
//정의하는 순서 중요
const doSomething = (person: string, age: number, isFunny: boolean) => {};
doSomething("은이", 11, true);
//함수 파라미터에 기본값 정하는 방법
function greet(person: string = "은이") {
return `hi there, ${person}`;
}
greet(); //아무것도 파라미터 입력하지 않아도 기본값 은이 적용
//Return 타입 애너테이션(명시해 주지 않아도 알아서 추정하여 반환하지만
//작성해주면 명확해서 선택사항임
// (파라미터:애너테이션) : 반환 타입
function square(num: number): number {
return num * num;
}
square(3);
// 배열의 경우
const numbers = [1, 2, 3];
numbers.map((num) => {
return num.toFixed();
});
//void 타입 return이 없을 경우에 알아서 void로 지정함
function printTwice(msg: string): void {
console.log(msg);
console.log(msg);
//return ""; //void 타입일 경우 리턴 불가
}
3. 객체 타입
//객체 타입 다루기
function printName(person: { first: string; last: string }): void {
console.log(`${person.first} ${person.last}`);
}
파라미터의 개수가 작을 때는 위와 같이 인라인으로 나열해도 되지만 ,
파라미터의 개수가 많을 경우에는 타입 별칭을 생성하여 별도로 관리하는 것이 좋다.
//타입 별칭 생성하기
type Point = {
x: number;
y: number;
};
//Point 타입 사용하여 함수 생성
//리턴 타입이 Point
function randomCoordinate(): Point {
return { x: Math.random(), y: Math.random() };
}
//중첩 객체 타입 애너테이션
type Song = {
title: string;
artist: string;
numStreams: number;
credits: {
producer: string;
writer: string;
};
};
function calculatePayout(song: Song): number {
return song.numStreams * 0.0033;
}
function printSong(song: Song): void {
console.log(`${song.title} - ${song.artist}`);
}
그리고 Type 을 생성할 때 선택적으로 프로퍼티를 생성할 수 있다.
//선택적 프로퍼티
type Point = {
x: number;
y: number;
z?: number; //선택적 프로퍼티 필수는 아님
};
//readonly 제어자
type User = {
readonly id: number; //읽기만 가능
username: string;
};
그리고 A type과 B type을 합쳐서 교차타입을 만들 수도 있다.
Circle type과 colorful 타입을 &을 사용하여 합쳐서 아래의 예시와 같이 사용 가능하다.
//교차 타입
type Circle = {
radius: number;
};
type Colorful = {
color: string;
};
// 위의 두 개의 타입을 합치고 싶을 때 & 사용
type ColorfulCircle = Circle & Colorful;
const happyFace: ColorfulCircle = {
radius: 4,
color: "yellow",
};
//그럼 만약에 교차타입 + 새로운 타입을 추가하고싶을때는?
type Cat = {
numLives: number;
};
type Dog = {
breed: string;
};
//교차 타입 + 나이(age) 추가
type CatDog = Cat & Dog & { age: number };
4. 배열 타입
//배열
const activeUsers: string[] = [];
activeUsers.push("은이");
activeUsers.push("은이2");
//activeUsers.push(1);//error
//배열 구문
const bools: Array<boolean> = [];
5. 유니온 타입
파라미터의 타입이 하나가 아니라면 유니온 타입을 사용하면된다.
//유니온 타입
let age: number | string = 21;
age = 23;
age = "24";
유니온 타입을 사용하면 age의 타입은 number 와 string 둘 다 사용할 수 있다.
type Point3 = {
x: number;
y: number;
};
type Loc = {
lat: number;
long: number;
};
let coordinates: Point3 | Loc = {
x: 1,
y: 34,
};
그리고, 이렇게 여러 타입을 받게 되면
그 뒤에 실행될 코드에서 문제가 생길 수도 있다.
예를 들어 number 타입의 경우에는 산수가 되지만, string 타입에는 불가능한것처럼
그러므로 타입 좁히기를 통해서 파라미터의 타입을 확인하고
그에 맞게 조건문으로 코드를 만들어주는 것이 좋다.
타입 좁히기는 여러 방법이 있으나 해당 강의에서는 typeof를 배웠다.
//유니온 타입으로 타입 좁히기
function calculateTax(price: number | string, tax: number) {
if (typeof price === "string") {
//타입이 string 일 경우 실행
price.replace("$", "");
} else {
price * tax;
}
}
그리고 또 신기한 기능은
리터럴 타입이라고
문자열이나 숫자에 정확한 값을 지정하여 더 엄격한 타입을 지정하는 것이다.
예를들어 어떤 함수에 파라미터를 받는 값이 yes 또는 no 라는 문자열만 들어오게 지정할 수 있음
아래와 같이 mood라는 변수는 "Happy" 또는 "Sad"라는 문자열만 받고 default값은 Happy다.
// 리터럴 타입
let mood: "Happy" | "Sad" = "Happy";
mood = "Sad";
//리터럴 타입
type DayOfWeek =
| "Monday"
| "Tuesday"
| "Wednesday"
| "Thursday"
| "Friday"
| "Saturday"
| "Sunday";
6. 튜플(Tuple)과 Enum
튜플은 길이와 각 요소마다의 타입이 고정된 배열이다.
//튜플
let myTuple: [number, string]; //배열의 순서 지정
myTuple = [10, "Typescript"]; //가능
//myTuple = ["Typescript", 10]; //ERROR 발생
//myTuple = [10, "Typescript",10]; //ERROR
//타입과 개수를 지정가능
// 숫자 타입 3개만 배열
const color: [number, number, number] = [3, 3, 3];
type HTTPResponse = [number, string];
const goodRes: HTTPResponse = [200, "OK"];
// const goodResError: HTTPResponse = [200, "OK", "error"]; // 에러 발생
//goodRes[0] = "200"; //number 타입 필요하므로 에러 발생
//튜플은 고정된 길이 타입의 배열이며, 배열 순서가 상관 있음
Enum : 변하지 않는 상수
//Enums
//enum은 명명된 상수의 집합임
enum OrderStatus {
PENDING = 10, // 10으로 지정하면 아래부터 +1씩됨
SHIPPED, // 11
DELIVERED, // 12
RETURNED, //13
}
const myStatus = OrderStatus.DELIVERED;
function isDelivered(status: OrderStatus) {
return status === OrderStatus.DELIVERED;
}
isDelivered(OrderStatus.RETURNED);
enum ArrowKeys {
UP = "up",
DOWN = "down",
LEFT = "left",
RIGHT = "right",
}
7. 인터페이스
type과 비슷한 역할을 한다. 하지만
type은 모든 타입을 선언할 때 사용할 수 있고, interface는 객체에 대한 타입을 선언할 때만 사용할 수 있다.
또한 확장 불가능한 타입을 선언하고 싶다면 type을 사용하면 되고, 확장 가능한 타입을 선언하고 싶다면 interface를 사용하면 된다.
https://velog.io/@wlwl99/TypeScript-type%EA%B3%BC-interface%EC%9D%98-%EC%B0%A8%EC%9D%B4
interface는 아래와 같이 사용한다.
type Point4 = {
x: number;
y: number;
};
interface Point4 {
x: number;
y: number;
}
type 과 동일하게 선택적 프로퍼티와 readonly도 사용가능함.
// 선택적 프로퍼티
interface Person {
readonly id: number; //readonly
first: string;
last: string;
nickname?: string; //선택적 프로퍼티 사용 가능
//sayHi : ()=> string //아무런 인수를 받지않고 문자열 타입을 반환하는 메서드
sayHi(): string;
}
하지만 차이점은 확장(상속)에 있다.
interface는 extends 를 사용하여 확장할 수 있다.
//인터페이스 확장
//인터페이스 + 새로운 프로퍼티를 추가하여 interface만들기
interface ServiceDog extends Dog {
// dog interface + job프로퍼티를 추가하여 serviceDog interface만들기
job: "job1" | "job2" | "job3";
}
그리고 type과 다르게 interface는 선언적 확장이 가능하다.
이미 만들어진 interface를 선언하면 자동으로 확장하는 것을 뜻한다.
//인터페이스는 작업 이후에도 새로운 프로퍼티를 추가할 수 있음
interface Person2 {
name: string;
}
interface Person2 {
age: number;
}
const person2: Person2 = {
name: "은이",
age: 27,
};
또한 다중 상속도 가능
//인터페이스 다중 상속
interface Human extends Person, Person2 {
level: string;
lan: string[];
}
8. 클래스
9. 제네릭
//제네릭
const nums: Array<number> = [];
const colors: Array<string> = [];
//제네릭 함수 작성하기
function numberIdentity(item: number): number {
return item;
}
function stringIdentity(item: string): string {
return item;
}
function booleanIdentity(item: boolean): boolean {
return item;
}
// //위와 같이 여러 개의 함수를 정의할 바에 any 타입으로 만들 수 있으나 바람직하지 않다.
// function identity(item: any): any {
// return item;
// }
// 이때 사용하는 것이 제네릭타입이다.
// 입력 타입에 따라 그 타입으로 반환한다는 관계를 설정
interface Cat {
name: string;
breed: string;
}
//T 는 type의 준말
function identity<T>(item: T): T {
return item;
}
identity<number>(7);
identity<string>("hello");
function getRandomElement<T>(list: T[]): T {
const randIdx = Math.floor(Math.random() * list.length);
return list[randIdx];
}
getRandomElement<string>(["a", "b", "c", "d"]);
여러 타입을 가진 제네릭을 사용할 때는 T,U를 사용한다.
//여러 타입을 가진 제네릭<T,U>
function merge<T, U>(object1: T, object2: U) {
return {
...object1,
...object2,
};
}
//제네릭 클래스 작성
interface Song {
title: string;
artist: string;
}
interface Video {
title: string;
creator: string;
resolution: string;
}
class VideoPlayList {
public videos: Video[] = [];
}
class SongPlayList {
public songs: Song[] = [];
}
class PlayList<T> {
public queue: T[] = [];
add(el: T) {
this.queue.push(el);
}
}
const songs = new PlayList<Song>();
const videos = new PlayList<Video>();
참고하기
https://velog.io/@naro-kim/TypeScript-Generic-%EC%A0%9C%EB%84%A4%EB%A6%AD
10. 타입좁히기(Narrowing)
위의 유니온 타입 설명할 때 타입 좁히는 방법 중 하나인 typeof를 배웠었다.
이번에는 그 외의 다른 방법들을 배웠다.
1. 동등 좁히기
// x와 y가 === 동등 연산자로 일치하기 위해서는 타입까지 동일해야함
function someDemo(x:string | number, y:string |boolean){
if(x === y){
}
}
2.instansOf
//instanseOf
function printFullDate(date: string | Date) {
if (date instanceof Date) {
console.log(date.toUTCString());
} else {
console.log(new Date(date).toUTCString());
}
}
3. typeof
https://www.udemy.com/course/typescript-with-webpack-react/
TypeScript 마스터 with Webpack & React
'FRONTEND > 기타' 카테고리의 다른 글
MonthPicker 라이브러리 모음 (0) | 2024.12.26 |
---|---|
Input -> type="number" 한글 자음 입력 방지 (0) | 2024.09.10 |
(API활용) 깃허브 유저찾기 app 2 (1) | 2023.11.14 |
(API활용) 깃허브 유저찾기 app 1 (1) | 2023.11.14 |
AJAX 기본 개념 및 예제 (1) | 2023.10.16 |