🍾 TypeScript ! 타입스크립트 기초 뿌수기 🕺
대망의 타입스크립트주차가 시작됐다.
타입스크립트 강의를 학습한 내용을 기록해 둔다.
TypeScript 왜 쓰는 걸까?
컴퓨터 언어는 Javascript 같은 동적언어(런타임에 타입이 결정되거나 오류를 발견한다)와 Java, TS와 같은 정적언어(컴파일 타임에 타입이 결정되거나 오류를 발견한다)로 나뉜다.
TS는 정적인 언어로 오류를 잡아내기 쉽다는 장점을 가진다. 또한 타입을 미리 결정하기 때문에 더욱 명시적인 코드를 작성하게 되고 후에 본인 혹은 다른 개발자가 확인하기에 용이한 코드를 작성하게 된다.\
function add(num1:number, num2:number) {
...
}
위 코드는 기본적인 예시이다.
만약 type을 설정하지 않으면 any type으로 설정된다.
TS의 기본 사용법
✍️ 변수 정의
let car:string = "bmw";
✅ string type이 아닌 값으로 재할당할 경우 error.
✅ TS가 할당된 값을 보고 자동으로 type을 부여한다. (타입추론)
✍️ Tuple 튜플
let b:[string, number];
✅ 배열의 길이가 고정되고 각 요소의 타입이 지정되어 있는 배열 형식.
✍️ void, never
function func:void() {
console.log("wow");
}
✅ void는 함수에서 return 값이 존재하지 않는 것을 의미한다.
✅ never 은 error을 반환하거나 영원히 끝나지 않는 함수를 의미한다.
✍️ enum
enum OS {
Window,
Ios,
Android,
}
✅ 비슷한 값들끼리 묶어준다.
✅ 숫자형 enum일 경우 양방향 래핑이 이루어진다.
OS["IOS"]; //1
OS[2]; //Android
✅예를 들어 window = 3; 으로 설정할 경우에는 Ios = 4, Android = 5가 된다.
✅ 숫자가 아닐 경우 단방향 래핑만 이루어진다.
✍️ null, undefined
let a:null = null;
let b:undefined = undefined;
✍️ Interface 인터페이스
let user:object;
user = {
name:"wow",
age: 30,
}
console.log(user.name) // error
✅ object에는 특정 속성 값에 대한 정보가 없기 때문에 error가 발생한다. 이럴 경우에 interface를 사용한다.
interface User {
name:string,
age:number,
gender?:string,
}
let user:User = {
name: "wow",
age:30,
}
user.age = 10;
user.gender = "female"
✅ gender? 에서? 는 옵션을 뜻한다. 값을 설정해도 설정하지 않아도 되는 옵셔널 하다는 의미이다.
✅ 만약 gender? 가 존재하지 않았다면 user.gender = "female"은 error 가 발생한다.
✍️ interface function
interface Add {
(num1:number, num2:number):number
}
const add:Add = function(x,y) {
return x+y;
}
✍️ interface class 선언과 사용
interface Car {
color:string,
wheels:number,
start():void
}
class Bmw implements Car {
constructor(c:string) {
this.color = c;
},
wheels = 4,
start() {
console.log("부릉~")
}
}
const b = new Bmw('grren');
✍️ 확장 인터페이스 extends
interface Benz extends Car {
// Car가 가진 속성들을 그대로 가져온다.
// 플러스알파를 설정할 수 있다.
door: number,
stop(): void,
...
}
✅ 복수의 interface로의 확장도 가능하다.
interface Car {
color:string,
whells:number,
start():void,
}
interface Toy {
name:string,
}
interface Toycar extends Car, Toy {
price:number,
}
✍️ readonly 읽기 전용 속성 (수정이 불가능)
readonly birth:number
✍️ 사용가능한 값을 한정하는 타입 만들기
type Score = "A" | "B" | "C" | "F";
✅ 만약, 타입을 Score로 정한다면 할당된 값들 중에서만 사용할 수 있다.
✍️ function 함수
function hello(name?:string) {
return `Hello, ${name||"world"}`;
}
✅ 매개변수인 name을 ?을 붙여 선택적 매개변수로 설정했다는 걸 알 수 있다.
function add(...nums) {
return nums.reduce((result, num) => result + num, 0);
}
✅ ...nums:number[]
✍️ 리터럴 타입 (= 변경 불가능한 타입)
const name1 = "Bob"; // name1:"Bob" 변경불가이기 때문에.
let name2 = "Tom"; // name2:string
name2 = 3; // error. 하지만 name2:string|number 로 명시적으로 표기해주면 error X
type Job = "teacher" | "developer" | "police";
interface User {
name:string,
job:Job, // Job타입에 할당된 값들 중에서만 사용 가능.
}
const user:User = {
name : "Bob",
job: "teacher",
}
✍️ 유니온 타입 (= 자바스크립트의 ||과 같은 의미. A or B)
interface Car {
name: "car",
color:string,
start():void,
}
interface Mobile {
name:"mobile",
color:string,
call():void,
}
function getGift(gift:Car | Mobile) {
console.log(gift.color); // Car, Mobile 둘 다 color를 가지고 있으므로 통과.
if(gift.name === "car") {
gift.start();
} else {
gift.call();
}
}
✅ 여러 타입들을 유니온타입(|)을 이용해서 연결할 수 있다.
✅ 동일한 속성의 값을 다르게 하여 식별가능하도록 하는 행위를 식별가능한 유니온타입이라 한다.
✍️ Intersection Types 교차 타입 (&)
✅ 여러 개의 타입을 하나로 합쳐준다.
const Toycar:Toy&Car {
// Toy와 Car의 속성을 모두 기재한다
}
✍️ class 선언과 할당
class Car {
constructor(color) {
this.color = color;
}
start() {
console.log("start");
}
} // 선언
const bmw = new Car("red");
✍️ 접근제한자 public / private / protected
✅ public (기본값) : 자식클래스, 클래스 인스턴스 모두 접근 가능
✅ private(혹은 #을 붙여서 사용) : 해당 클래스 안에서만 접근 가능
private name:string = "car";
#name:string = "car";
// 둘은 같다.
✅ protected : 자식 클래스에서 접근 가능하지만 클래스인스턴스로는 존재하지 않는다.
✍️ static
✅ static으로 선언된 경우 this가 아니라 클래스명으로 호출한다.
✍️ abstract (추상클래스를 만들 때)
✅ new를 사용해 객체를 만들 수 없고, 상속(extends)을 통해서만 사용이 가능하다.
abstract class User {
...
}
✍️ 추상화
✅ 메서드나 프로퍼티의 이름만 선언해 주고 구체적인 기능은 상속받는 쪽에서 구현하는 것을 의미한다.
✍️ generic 제네릭
✅ 제네릭을 이용하면 클래스, 함수, 인터페이스 다양한 타입으로 재사용이 가능하다.
✅ 선언할 때는 타입, 파라미터만 적어주고 생성하는 시점에 사용하는 타입을 결정한다.
function getSize(arr:number[]|string[]|...):number{
return arr.length;
}
✅ 예시 코드의 경우, 유니온을 이용하여 계속해서 추가할 수 있지만 그때그때 추가해야 하는 번거로움, 길어지는 코드 등의 문제가 생긴다. 이럴 때 제네릭을 사용한다.
function getSize<T>(arr:T[]):number { return arr.length; }
const arr1 = [1,2,3];
getSize<number>(arr1); // 사실 TS는 알아서 판단해주지만 더더욱 명시적으로 표현하고 싶을 때는 <number> 이런식으로
✅ T는 타입파라미터라는 뜻으로 사실 다른 글자를 넣어도 된다. 하지만 T를 일반적으로 사용한다.
✅ 해당 함수를 사용할 때 타입을 설정해주고 있는 걸 볼 수 있다.
✍️ 유틸리티 타입
✨ keyof
interface User {
id:number;
name:string;
age:number;
gender:'m' | 'f';
}
type UserKey = keyof User; // 'id' | 'name' | 'age | 'gender'
✨ Partial <T>
프로퍼티를 모두 옵셔널로 바꿔준다.
✨ Required <T>
모든 프로퍼티를 필수로 바꿔준다.
✨ Readonly <T>
읽기 전용. 수정 불가.
✨ Record <Key, Type>
✨ Pick <T, K> / Omit <T, K>
Pick : 특정 프로퍼티만 선택
Omit : 특정 프로퍼티만 생략
✨ NonNullable <Type>
null, undefined를 제외
✨ Exclude <T1, T2>
T2와 겹치는 부분 제외