될때까지

((Typescript)) 기초 개념 본문

학습/JavaScript, TypeScript

((Typescript)) 기초 개념

랖니 2022. 10. 31. 21:20
728x90

타입스크립트를 사용하는 이유

자바스크립트는 동적 타입 언어로 런타임 때 타입이 결정되지만, 타입스크립트는 자바스크립트에 타입을 얹은 정적 타입 언어다. 
타입스크립트는 컴파일 작업을 할 때 데이터 타입으로 인한 문제를 미리 알려주고 이로 인해 사전의 버그를 방지할 수 있다.

 

Type

// string, number, boolean
let age:number = 30;
let isAdult:boolean = true;

// array
let a1:number[] = [1,2,3];
let a2:Array<number> = [1,2,3];

let week1:string[] = ['mon', 'tue', 'wed'];
let week2:Array<string> = ['mon', 'tue', 'wed'];

// tuple
let b1:[string, number];
b1 = ['z', 1];  // 가능
// b1 = [1, 'z'];  // 불가능

// void => 함수에서 아무것도 반환하지 않을 때 사용
function sayHello():void {
	console.log('아무것도 반환하지않음');
}

// any => 어떤 타입도 지정 가능(웬만하면 쓰는 것을 지양하자 - 타입스크립트 사용 이유가 없어짐)
let value:any;
value = 'kim';
value = 123;
value = [1,2,3,4];  // 모두 에러없이 실행된다.

// never => #1.에러를 반환하거나 
function showError():never {
	throw new Error();
}

// never2 => #2.영원히 끝나지 않는 함수에 사용
function infLoop():never {
	while (true) {
    	// do something...
    }
}

// enum => 상수(변하지 않는 값)로된 세트의 값이 필요할 때 사용
enum Menu {
    Pasta,
    Pizza,
    Soup
}

// menuCategory 변수는 Menu타입으로 해당 enum값 중 하나를 가질 수 있다.
let menuCategory:Menu = Menu.Pasta;

// Menu의 Pasta라는 값을 menuCategory 변수에 할당하면 0이 저장된다.
// 특정값이 없는 Enum의 경우 0부터 값이 주어지고, 차례대로 1,2가 Pizza, Soup에 주어지기 떄문이다.
console.log(Menu.Pasta);    // 0
console.log(Menu.Pizza);    // 1
console.log(Menu.Dessert);  // 2

// Enum에 특정 값을 할당하고 싶다면 아래와 같이 지정해주면 된다.
enum Menu {
    Pasta = '파스타',
    Pizza = '피자',
    Soup = '수프'
}

console.log(Menu.Pasta);    // 파스타



// null, undefined
let a:null = null;
let b:undefined = undefined;

 

 

Interface

let user:object;

user = {
    name: 'xx',
    age: 30
}

console.log(user.name);  // Error : Property 'name' does not exist on type 'object'

💎 객체의 타입정의하기 위해서는 인터페이스를 사용하면 된다.

interface User {
    name: string;
    age: number;
}

let user:User = {
    name: 'xx',
    age: 30
}

💎  있어도 되고 없어도 되는 프로퍼티를 정의할때는 변수명 뒤에 물음표를 붙이면 된다.

interface User {
    name: string;
    age: number;
    gender?: string;
}

let user:User = {
    name: 'xx',
    age: 30
}

user.gender = 'male';

💎 readonly : 읽기 전용 속성으로 해당 프로퍼티를 수정 불가하게 만든다.(최초 생성시에만 값 할당이 가능)

interface User {
    name: string;
    age: number;
    gender?: string;
    readonly birthYear: number;
}

let user:User = {
    name: 'xx',
    age: 30
    birthYear: 2000
}

user.gender = 'male';
user.birthYear = 1990;  // Error : Cannot assign to 'birthYear' because it is a read-only property.

💎 type : 문자열 리터럴 타입을 사용하여 원하는 타입만 들어오도록 지정이 가능하다.
(literal은 변하지 않는 데이터 그 자체를 의미함)

type Score = 'A' | 'B' | 'C' | 'F'

interface User {
    name: string;
    age: number;
    gender?: string;
    readonly birthYear: number;
    [grade:number]: Score;
}

let user:User = {
    name: 'xx',
    age: 30
    birthYear: 2000,
    1: 'A',
    2: 'c',  // 에러 발생  => Score에서 지정된 타입만 입력가능함
}

💎 함수 인터페이스 

interface Add {
    (num1:number, num2:number):number;
}

const add:Add = function (x,y) {
    return x + y;
}

add(10,20);

interface IsAdult {
    (age:number):boolean;
}

const isAdult:IsAdult = (age) => {
    return age > 19;
}

isAdult(18);

💎 implements : 클래스 인터페이스

interface Car {
    color:string,
    wheels:number;
    start():void;
}

class Bmw implements Car {
    color = 'red',
    wheels = 4,
    start() {
        console.log('부릉부릉');
    }
}

💎 extends : 확장

interface Car {
    color:string,
    wheels:number;
    start():void;
}

interface Benz extends Car {
    door:number;
    stop():void;
}

const benz:Benz = {
    color : 'red',
    wheels : 4;
    start() {
        console.log('출발!!');   // Car에 있는 속성들도 모두 입력해야함
    };
    door : 5;
    stop() {
        console.log('스톱!!');
    }
}

 

Function

💎 선택적 매개변수 : ? 물음표 사용

function hello(name?: string) {
    return `Hello, ${name || 'noname'}`;   // 위에서 name옆에 물음표를 붙이지 않으면 제대로 작동되지않는다.
}

const result = hello();

💎 선택적 매개변수는 필수 매개변수보다 앞에 올 수 없다. 뒤에 배치하거나

function hello(age?: number, name: string): string {   // 에러발생
    if (age !== undefined) {
        return `Hello, ${name}. You are ${age}.`;
    } else {
        return `Hello, ${name}`;
    }
}

console.log(hello(30, 'Sam'));

💎 선택적 매개변수는 | undefined라고 명시해준다.

function hello(age: number | undefined, name: string): string {   
    if (age !== undefined) {
        return `Hello, ${name}. You are ${age}.`;
    } else {
        return `Hello, ${name}`;
    }
}

console.log(hello(undefined, 'Sam'));

💎 나머지 매개변수

function add(...nums: number[]) {
    return nums.reduce((result, num) => result + num, 0);
}

add(1,2,3);
add(1,2,3,4,5,6,7,8,9,10);

💎 this

interface User {
    name: string;
}

const Sam: User = {
    name : "Sam"
}

function showName(this:User, age:number, gender:'m' | 'f') {
    console.log(this.name, age, gender)
}

💎 overloading : 매개변수의 개수나 타입이 다르지만 이름이 동일한 함수

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);
const jane: string = join("Jane", "30");

 

유니언/교차 타입

유니언 ' | ' : or의 느낌 => 여러 타입 중 하나

교차 ' & ' : and의 느낌 => 여러 타입을 합쳐서 하나

 

Class

class Car {
    constructor(color: string) {
        this.color = color;   // Error : Property 'color' does not exist on type Car
    }
    start() {
        console.log('start');
    }
}

const bmw = new Car("red");


class Car2 {
    color: string;  // 멤버변수는 미리 선언해줘야한다
    constructor(color: string) {
        this.color = color;  
    }
    start() {
        console.log('start');
    }
}

const bmw = new Car("red");

💎 멤버변수는 미리 선언하거나 접근 제한자를 사용해야 한다.

// 접근제한자(Access modifier) => public, private, protected
// public : 자식 클래스, 클래스 인스턴스 모두 접근 가능
// protected : 자식 클래스에서 접근 가능
// private or #변수명 : 해당 클래스 내부에서만 접근 가능
class Car {
    name: string = "car";
    color: string;
    constructor(color: string) {
        this.color = color; 
    }
    start() {
        console.log('start');
    }
}

class Bmw extends Car {
    constructor(color: string) {
        super(color);
    }
    showName() {
        console.log(super.name);
    }
}

const z4 = new Bmw("black");

💎 static : 정적 멤버변수 => this.이 아닌 class.으로 접근 가능

class Car {
    name: string = "car";
    color: string;
    static wheels = 4;
    constructor(color: string) {
        this.color = color; 
    }
    start() {
        console.log('start');
        console.log(Car.wheels);   // 클래스. 으로 호출
    }
}

class Bmw extends Car {
    constructor(color: string) {
        super(color);
    }
    showName() {
        console.log(super.name);
    }
}

const z4 = new Bmw("black");
console.log(Car.wheels);    // 클래스. 으로 호출

💎 추상 클래스

abstract class Car {
    color: string,
    constructor(color: string) {
        this.color = color;
    }
    start() {
        console.log("start");
    }
}

const car = new Car("red");   // Error : 추상클래스는 new로 객체 생성 불가

class Bmw extends Car {       // extends를 사용하여 생성해야한다.
    constructor(color: string) {
        super(color);
    }
}
abstract class Car {
    color: string,
    constructor(color: string) {
        this.color = color;
    }
    start() {
        console.log("start");
    }
    abstract doSomething(): void;    // 추상메소드 생성
}

const car = new Car("red");   

class Bmw extends Car {
    constructor(color: string) {
        super(color);
    }
    doSomething() {
        alert(3);     // 추상메소드는 상속받는 쪽에서 구체적인 기능을 정의해야한다.
    }
}

 

* 참고영상

https://adjh54.tistory.com/32

https://www.youtube.com/playlist?list=PLZKTXPmaJk8KhKQ_BILr1JKCJbR0EGlx0

728x90