타입스크립트를 사용하는 이유
1. 우리가 사용하는 브라우저는 타입스크립트를 이용하지 못함.
2. 함수을 만들 때 의도했던 방식외에 다른 방식을 에러로 인식할 수 있음
3. 다른 사람이 만든 함수를 사용할 때 몇개의 함수를 어떤 타입으로 사용해야 하는지 찾아볼 필요 없음
타입스크립트 기본 타입
string
let car = "sonata"
let car:string = "sonata"
// Array
let a:number[] = [1, 2, 3];
let a2:Array<number> = [1, 2, 3]
// Tuple
let b:[string, number];
b = ['z', 1]
// void 아무것도 리턴하지 않는 함수
// never 에러반환 혹은 끝나지 않는 타입
// enum
enum Os{
window,
IOS,
Android,
}
// null, undefined
interface
인터페이스란
type Score = 'A' | 'B' | 'C' | 'D';
interface User {
name: string;
age: number;
gender? : string // 없을 수 도 있음
readonly birthYear : number // 읽기 전용
[grade: number] : Score // number를 key로 하고 string을 value로 하는 property를 여러개 받을 수 있다.
}
let user : User = {
name: 'xx'
age : 30
birthYear : 2000,
}
interface로 함수 정의하기
내부에 괄호와 인자값, 리턴값을 정해주면 됨
interface Add{
(num1: number, num2:number): number;
}
const add : Add = function(x, y){
return x + y;
}
add(10, 20)
나이를 받아서 성인인지 아닌지 return 하는 함수
interface isAudult {
(age:number):boolean;
}
const a:isAudult = (age) => {
return age > 19;
}
a(33) // true
interface로 class 정의하기
-> implements
interface 확장
-> extends
interface Car {
color: string;
wheels: number
start(): void
}
interface Benz extends Car {
door : number;
stop(): void;
}
const benz : Benz = {
door : 5,
stop() {
console.log('stop');
color : 'black'
wheels : 4
start(){}
}
}
class BMW implements Car {
color;
sheets = 4
constructor(c:tring){
this.color = c;
}
start(){
console.log('go..')
}
}
const b = new BMW('green');
console.log(b)
b.start(); // "go..."
function hello(name?: string) {
return `Hello, ${name || "world"`;
}
// name이 있으면 name을, 없으면 "World"를 return
const result = hello();
const result2 = hello("John"); // Hello John
function hello2(name = "world") {
return `Hello, ${name}`; // 자바스크립트 기본값 사용법
}
name: 필수적 매개변수
age: 선택적 매개변수
선택적 매개변수는 일반적으로 맨 앞에 올 수 없음(없어도 되는 매개변수니까)
function hello(name: string, age?: number): string {
if (age !== undefined) {
return `Hello, ${name}, You are ${age}.`;
} else {
return `Hello, ${name}`;
}
}
console.log(hello("Sam"));
console.log(hello("Sam", 30));
rest Parameter(나머지 매개변수)
function add(...nums) {
return nums.reduce((result, num) => result + num, 0);
}
add(1, 2, 3); // 6
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 55
this
interface User {
name: string;
}
const Sam: User = {name: 'Sam'}
function showName(this:User){
console.log(this.name)
}
cons a = showName.bind(Sam);
a();
function showName2(this:User, age:nuber, gender:'m'|'f'){
console.log(this.name, age, gender)
}
cons a = showName.bind(Sam);
a(30, 'm');
오버로드: 함수오버로드란 전달받은 매개변수의 개수나 타입에 따라 다른 동작을 하게 하는 것
interface User {
name: string;
age: number;
}
// 함수 오버로드
function join(name: string, age: string) : string;
function join(name: string, age: number) : User
function join(name: string, age: number | string): User | string {
if (typeof age === "number") {
return {
name,
age,
};
} else {
return "나이는 숫자로 입력해 주세요";
}
}
const sam: User = join("Sam", 30); // name이 string, age가 number
const jane: string = join("Jane", "30") // name, age가 모두 string
리터럴, 유니온/교차 타입
// Literal Types
const userName1 = "Bob";
let UserName2: string | nmber = "Tom";
userName2 = 3;
type Job = "police" | "developer" | "teacher";
interface User {
name : string;
job : "developer"
};
interface HichSchoolStudent {
name: number | string;
grade: 1 | 2 | 3; // Union Type
}
// Union Types
interface Car {
name: "car";
color: string;
start(): void;
intercafe Mobile {
name: "mobile";
color: string;
call(): void;
function getGift(gift: Car | Mobile) {
console.log(gift.color);
if (gift.name === "car") {
gift.start();
} else {
gift.call();
}
}
// 검사해야할 항목이 많아지면 switch를 사용하는 것이 좋음
// 동일한 속성의 타입을 다르게 하는것을 식별 가능한 union type이라고함
intersection Types
// intersection types
interface Car {
name: string;
strat(): void;
}
interface Toy {
name: string;
color: string;
price: number;
}
// 교차타입은 여러가지 타입을 하나로 합쳐주는 역할
// 필요한 모든 기능을 가진 하나의 타입을 만들 수 있음
const toyCar: Toy & Car = {
name: "타요",
start() {},
color: "blue",
price: 1000,
}
``선행 자료 자바스크립트 중급 강좌 #15 클래스(Class)
ES6에서는 접근제어자를 지원하지 않음
TS는 접근제어자를 지원함
public: 자식클래스나 class instance에서 접근이 가능함, default 값임
private: 자식클래스 내부에서 사용할 수 없게됨, 해당 클래스에서만 사용할 수 있게함
-> #parameter 으로도 같은 기능을 사용할 수 있음
protected: 자식클래스에서는 통제할 수 있고, 클래스 인스턴스로는 통제할 수 없음
class Car {
color: string;
static wheels = 4; // static 사용하면 this가 아닌 class명을 사용해줌
constructor(color: string){ // public or readonly 사용
this.color = color;
}
start() {
console.log("start");
}
}
const bmw = new Car("red");
class Bmw extends Car {
constructor(color: string) {
super(color);
}
showName() {
console.log(sper.name);
}
}
const 24 = new Bmw("black");
추상클래스
abstract class Car {
color: string;
constructor(color: string) {
this.color = color;
}
start() {
console.log("start");
}
}
// const car = new Car("red");
class Bmw extends Car {
constructor(color: string) {
super(color);
}
doSomethig(){
alert(3);
}
}
generic
클래스나 함수, 인터페이스를 다양한 타팁으로 재사용 가능
선언할때는 타입 파라미터만 적어주고 생성하는 시점에 사용하는 타입을 결정
// Generic
function getSize(arr: number[]): number {
return arr.length;
}
const arr1 = [1, 2, 3];
getSize(arr1);
Generic 미사용시
function getSize(arr: number[] | string[] | boolean[]): number {
return arr.length;
}
const arr1 = [1, 2, 3];
getSize(arr1); // 3
const arr2 = ["a", "b", "c"];
getSize(arr2); // 3
const arr3 = [false, true, true];
getSize(arr3); // 3
Generic 사용
전달되는 매개변수에 따라서 타입이 달라짐
function getSize<T>(arr: T[]): number {
return arr.length;
}
const arr1 = [1, 2, 3];
getSize(arr1); // 3
const arr2 = ["a", "b", "c"];
getSize(arr2); // 3
const arr3 = [false, true, true];
getSize(arr3); // 3
Generic 예제 2. interface 에서 사용해 보기
interface Mobile<{color: string; copon: boolean}> = {
name: string;
price: number;
option: T;
const m1: Mobile = {
name: "s21",
price: 1000,
optionP
color: "red",
coupon: false,
},
};
const m2: Mobile<string> = {
name: "s20",
price: 900,
option: "good"
};
Generic은 코드 재사용시 장점이 많음
interface의 정의에 대해서 알아보기
// keyof
// 유저 인터페이스의 값들을 키값으로 받을 수 있음
interface User {
id: number;
name: string;
age: number;
gender: "m" | "f";
}
type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'
const uk: UserKey = "id"
const uk: UserKey = "none" // error
interface User {
id: number;
name: string;
age: number;
gender: "m" | "f";
}
let admin: Partial<User> = {
id: 1,
name: "Bob",
};
interface User {
id: number;
name: string;
age?: number; // age가 필수는 아님
}
let admin: Required<User> = { // Required를 넣어서 모든 property를 필수로 정하기
id: 1,
name: "Bob"
age: 30,
};
interface User {
id: number;
name: string;
age?: number; // age가 필수는 아님
}
let admin: Readonly<User> = {
id: 1,
name: "Bob",
};
admin.id = 4; // Readonly로 선언하기 전에는 값을 바꿀 수 있음
admin.id = 4; // Readonly로 선언하고 난후에는 error 발생
interface Score {
"1": "A" | "B" | "C" | "D";
"2": "A" | "B" | "C" | "D";
"3": "A" | "B" | "C" | "D";
"4": "A" | "B" | "C" | "D";
}
const score: Score = {
1: "A",
2: "B",
3: "C",
4: "D",
};
// -----------
type Grade = "1" | "2" | "3" | "4";
type Score = "A" | "B" | "C" | "D";
const score: Record<Grade, Score> = {
1: "A",
2: "B",
3: "C",
4: "D",
};
interface User {
id: number;
name: string;
age: number;
}
function isValid(user: User) {
const result: Record<keyof User, boolean> = {
id: user.id > 0,
name: user.name !== "",
age: user.age > 0,
}
return result;
}
인터페이스에서 원하는 프로퍼티만 가져와서 사용하기
interface User {
id: number;
name: string;
age: number;
gender: "M" | "W"
}
const admin: Pick<User, "id" | "name"> = {
id: 0,
name: "Bob",
};
특정 프로퍼티를 생략하고 사용하기
interface User {
id: number;
name: string;
age: number;
gender: "M" | "W"
}
const admin: Omit<User, "age" | "gender"> = {
id: 0,
name: "Bob",
};
// User interface에서 age와 gender를 제외한 property를 사용(id, name)
Type1에서 Type2를 제외하고 사용
타입으로 제거 하는 차이가 있음
type T1 = string | number;
type T2 = Exclude<T1, number>;
// T2에서 number를 제외한 값으로 적용
Null과 undefined를 제외한 값을 생성
type T1 = string | null | undefined | void;
type T2 = NonNullabe<T2> // 타입에 string, void만 남게됨