Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ksw_devlog

TIL 12주 4일차- Type script 본문

TIL

TIL 12주 4일차- Type script

kimcoach 2023. 1. 19. 20:36

Class에서 Type script 복습

 

class Car {
    model :string;
    price :number;
    constructor(a :string, b :number){
        this.model = a;
        this.price = b;
    }
    tax() :number{
        return this.price * 0.1
    }
}

let car1 = new Car('소나타', 3000)
console.log(car1.tax())
console.log(car1)

--------

class Word {
    num;
    str;
    constructor(...param : any[]){
        let nums :number[] = [];
        let strs :string[] = [];
        param.forEach((i)=>{
            if(typeof i === 'string'){
                strs.push(i)
            } else {
                nums.push(i)
            }
        })
        this.num = nums;
        this.str = strs;
    }
}
let obj = new Word('kim', 3, 5, 'park')
console.log(obj.num)
console.log(obj.str)

 


Object에 쓸 수 있는 interface 문법 

 

interface 문법을 쓰시면 object 자료형의 타입을 보다 편리하게 지정가능합니다.

예를 들어서 { color : 'red', width : 100 }

이런 object를 만들고 싶은데 type을 미리 정의하고 싶으면 interface 키워드를 이렇게 만들어봅시다. 

 

interface Square { 
  color :string, 
  width :number, 
} 

let 네모 :Square = { color : 'red', width : 100 } 

 

interface는 object랑 비슷한 모습으로 작성하면 됩니다. 

type alias와 용도와 기능이 똑같습니다. 

1. 대문자로 작명하고 2. { } 안에 타입을 명시해주면 됩니다. 

만들어두면 앞으로 object자료 만들 때 interface 만든걸 집어넣으시면 간편하게 타입지정이 가능합니다.

(참고) 한 줄 끝나면 콤마대신 세미콜론도 가능합니다. 

 

interface 장점은 extends도 가능합니다

 

Student interface & Teacher interface가 필요하다고 가정해봅시다.

Student는 name 속성이 들어가야하고 

Teacher는 name 속성과 age 속성이 들어가야합니다. 

 

interface Student {
  name :string,
}
interface Teacher {
  name :string,
  age :number,
}

Student interface와 Teacher interface와 중복되는게 보임.

이런건 extends 문법쓰시면 줄일 수 있습니다. 

extends 문법은 interface 여기에 복사해달라는 뜻입니다. 

 

interface Student {
  name :string,
}
interface Teacher extends Student {
  age :number
}

Student interface를 extends 해달라고 적으면 Student 안에 있던걸 복사해서 Teacher에 넣어줍니다.

이제 Teacher 타입은 age, name 속성을 가지고 있습니다.

 

type 키워드와의 차이점

 

type alias와 interface는 거의 똑같은 기능을 제공합니다. 

그래서 차이점은 extends 문법이 약간 다르다 이런건데

 

interface Animal { 
  name :string 
} 
interface Cat extends Animal { 
  legs :number 
}

interface의 경우 일반적으로 이렇게 extends 합니다. 

 

 

type Animal = { 
  name :string 
} 
type Cat = Animal & { legs: number }

type alias의 경우 extends는 안되고 & 기호를 쓰면 object 두개를 합칠 수 있습니다.

이러면 Cat 타입은 name, legs 속성을 가질 수 있습니다. 

 

 

 

실은 interface도 type처럼 & 기호를 이용해도 복사가능 

interface Student {
  name :string,
}
interface Teacher {
  age :number
}

let 변수 :Student & Teacher = { name : 'kim', age : 90 }

& 기호 쓰는걸 intersection이라고 부르는데 extends 와 유사하게 사용가능합니다. 

(주의) extends 쓸 때 타입끼리 중복속성이 발견될 경우 에러로 혼내주는데 & 쓰면 때에 따라 아닐 수도 있습니다.

 

타입이름 중복선언시

 

interface Animal { 
  name :string 
} 
interface Animal { 
  legs :number 
}

interface의 경우 타입이름 중복선언을 허용해주며 중복시 extends 한 것이랑 동일하게 동작합니다. 

이러면 Animal 타입은 name, legs 속성을 가질 수 있습니다. 

(장점) type 선언을 자주 쓰는 외부 라이브러리 이용시 type 선언을 내가 덮어쓰기, override 하기 편리합니다.

 

 

 

type Animal = { 
  name :string 
} 
type Animal = { 
  legs :number 
}

type의 경우 중복선언을 허용하지 않습니다. 에러남

(장점) 엄격하고 진지함 

 

 

 

그래서 일반적인 상황에선 type 키워드 자주 활용하면 되는데 

다른 사람이 내 코드를 이용하는 상황이 많으면 interface로 유연하게 만드는게 좋습니다. 

그래서 타입스크립트로 작성된 라이브러리들은 interface로 타입정해놓은 곳이 많습니다. 

혹은 object 자료형은 전부 interface로 만들고 다른 자료형은 type 키워드로 만들고 이런 것들도 괜찮습니다.

type과 interface 문법을 잘 알고 있으면 기준은 정하기 나름입니다. 

 

extend 할 때 object 안의 속성이 중복될 경우

 

interface Animal { 
  name :string 
} 
interface Dog extends Animal { 
  name :number 
}

Animal을 복사해서 Dog interface를 만들어봤습니다.

근데 name 속성이 중복되네요? 그럼 에러납니다 끝

 

 

 

 

interface Animal { 
  name :string 
} 
interface Dog { 
  name :number
} 

let 변수 :Dog & Animal = { name : '멍멍' }

& 연산자로 Dog, Animal을 합쳐봤습니다.

근데 name 속성이 중복되네요? 그럼 에러납니다 끝

interface 말고도 type 키워드도 똑같은 현상이 일어납니다. 

 

(주의) 근데 name : string , name : number 라서 에러가 나는 것이지

둘다 name : string 타입이면 에러가 나지 않습니다. 하나로 합쳐줌 

 

 

object 안에 함수를 2개 넣기

 

interface MathObj {
  plus : (a:number, b:number) => number,
  minus : (a:number, b:number) => number
}

let 오브젝트 :MathObj = {
  plus(a,b){
    return a + b
  },
  minus(a,b){
    return a - b
  }
} 

 

함수타입은 ()=>{} 

--------

interface Product {
    brand : string,
    serialNumber : number,
    model : string[]
}

let 상품 : Product = {brand : 'Samsung', serialNumber : 1360, model : ['TV', 'phone']}

interface Market {
    product : string,
    price : number
}
let cart : Market[] = [{product : '청소기', price : 7000}, {product : '삼다수', price : 800}]

interface NewMarket extends Market {
    card : boolean
}

interface Calculation {
   plus : (a: number, b : number) => number,
   minus : (a: number, b :number) => number
}
let mathobj : Calculation = {
    plus(a,b) {
        return a + b;
    },
    minus(a, b) {
        return a -b;
    }
}

 


잠깐 rest 파라미터 개념설명

 

리액트 때문에 계속되는 자바스크립트 기초학력 저하현상으로 잠깐만 JS 문법설명을 하자면 

함수에 어떤 파라미터가 몇개 들어올지 미리 정의가 불가능한 경우가 있습니다. 

3개일지 4개일지 100개일지 모른다면 점3개 ...로 rest 파라미터를 만들어주면 됩니다.

 

function 전부더하기(...a){
  console.log(a)
}

전부더하기(1,2,3,4,5)

함수 파라미터 작명할 때 점3개 붙여주면 여기엔 파라미터 잔뜩 들어올 수 있습니다~라고 정의가 가능합니다. 

 

전문 용어로 rest 파라미터라고 합니다.

- rest 파라미터는 다른 일반 파라미터 뒤에만 올 수 있습니다. 

- rest 파라미터자리에 집어넣은 값들은 전부 [ ] 안에 담겨있습니다. 

 

rest 파라미터 타입지정은

 

function 전부더하기(...a :number[]){
  console.log(a)
}

전부더하기(1,2,3,4,5)

rest 파라미터는 항상 [ ] 안에 담겨오기 때문에 타입지정도 array처럼 해주시면 됩니다.

 

Spread operator와 다른겁니다

 

코드짜다보면 점 3개 붙이는 경우가 또 있는데

array 혹은 object 괄호 벗기고 싶을 때 왼쪽에 사용합니다.

let arr = [3,4,5];
let arr2 = [1,2, ...arr]
console.log(arr2)

array 혹은 object 왼쪽에 점3개 붙이면 괄호 벗겨주세요~ 라는 뜻입니다.

그래서 arr2 출력해보면 [1,2,3,4,5] 나옵니다. 

 

괄호벗겨주는 ...spread는 array, object 자료 왼쪽에,

여러개의 파라미터를 의미하는 ...rest는 함수선언할 때 소괄호 안에 출몰합니다. 

 

잠깐 Destructuring 문법 개념설명

 

잠깐 다시 JS 문법설명 하나만 합시다. 

자바스크립트에서 array, object 안에 있는 데이터를 빼서 변수로 만들고 싶을 때 쓰는 문법이 있습니다. 

 

let 사람 = { student : true, age : 20 }
let student = 사람.student;
let age = 사람.age

이렇게 쓰면 되긴 하는데 개발자들이 귀찮아서 새로운 문법을 만들어냈습니다. 

Destructuring 이라는 것인데 변수로 빠르고 쉽게 뺄 수 있도록 도와주는 문법입니다. 

 

 

 

let { student, age } = { student : true, age : 20 }

이렇게 쓰면 똑같이 변수로 뺄 수 있습니다. 

진짭니다 student 한 번 출력해보셈 true 들어있을 걸요 

이걸 destructuring 문법이라고 하며 왼쪽 오른쪽 틀린그림찾기처럼 변수 작명해주시면 끝입니다. 

 

let [a, b] = ['안녕', 100]

array 자료도 왼쪽오른쪽 똑같아보이게 변수 작명해주시면 변수로 쉽게 뺄 수 있습니다. 

다만 특징은 object destructuring할 땐 변수이름을 속성이름과 맞춰주는게 편리하고 (안맞추면 더 복잡함)

array destructuring할 땐 변수이름 맘대로 작명가능합니다. 

 

Destructuring 문법도 함수 파라미터에 사용가능

 

왜냐면 함수 파라미터 작명하는 것도 변수만드는 문법과 똑같아서 그렇습니다 

변수만들 때 기존 object에 있던 자료를 파라미터로 집어넣고 싶으면 

 

 

let person = { student : true, age : 20 }

function 함수(a, b){
  console.log(a, b)
}
함수(person.student, person.age)

기존 object에 있던걸 person.student 이렇게 각각 찝어서 집어넣으면 되긴 되는데

destructuring 문법을 이용하면 약간 더 쉽게 사용가능합니다. 

 

 

let person = { student : true, age : 20 }

function 함수({student, age}){
  console.log(student, age)
}
함수({ student : true, age : 20 })

그니까 파라미터 변수만들 때 { student, age }라고 쓰면

파라미터로 들어오는 { student : 어쩌구 }는 student 라는 변수에 저장해주세요~

파라미터로 들어오는 { age : 어쩌구 }는 age 라는 변수에 저장해주세요~

라는 뜻입니다. (object 자료니까 변수 작명할 때 object 속성명으로 잘 작명해야함)

항상 같은 모습의 object, array 자료가 들어올 때 쓰는 문법이라고 보면 되겠습니다.

 

-----

//최댓값 출력하는 함수
function 최댓값(...param : number[]): number {
    let result = 0;
    param.forEach((i)=>{
        if (result < i){
            result = i
        }
    })
    return result;
}
console.log(최댓값(4,6,3,2))

// destructuring object
function Test({user, comment, admin} :
    {user : string, comment : number[], admin : boolean}) :void{
    console.log(user, comment, admin);
}
Test({user : 'kim', comment : [3, 5, 4], admin : false})

// destructuring array
function Quiz([a, b, c] : [a:number, b:string, c:boolean]){
    console.log(a, b, c)
}
Quiz([40, 'wine', false])
===

type 어레이 = (number | string | boolean)[];

function 함수([a,b,c]:어레이){
  console.log(a,b,c)
}

함수( [40, 'wine', false] )

 


in 연산자로 object 자료 narrowing

예를 들어서 파라미터로 object가 2개 들어올 수 있다고 타입지정을 해놓은 것입니다.

하나는 {a : 'kim}

다른 하나는 {b : 'park'}

이렇게 서로 다른 유니크한 속성들을 가지고 있다면

 

if (이 파라미터가 a라는 속성을 안에 가지고 있냐)

이런 if문을 써도 narrowing이 가능하다는 뜻입니다.

if (키값 in object자료형) 이렇게 쓰면 됩니다.

타입스크립트 컴파일러는 똑똑한 편이라 이런 것들도 narrowing 으로 판정해줍니다. 

type Fish = { swim: string };
type Bird = { fly: string };
function 함수(animal: Fish | Bird) {
  if ("swim" in animal) {
    return animal.swim
  }
  return animal.fly
} 

서로 배타적인 속성을 가져와야 narrowing이 가능합니다.

예를 들어서 Fish와 Bird 타입이 둘 다 swim 속성을 가지고 있고 Bird만 fly 속성을 추가로 가지고 있으면 어쩌죠?

어떻게 narrowing하면 좋을지 한 번 생각해봅시다. 

 

class로부터 생산된 object라면 instanceof로 narrowing

 

class 문법을 아는 분들만 들어보도록 합시다. 

어떤 클래스로부터 new 키워드로 생산된 object들이 있습니다.

그런 object 들은 instanceof 키워드를 붙여서 부모 클래스가 누군지 검사할 수 있는데

이것도 narrowing 역할을 할 수 있습니다.

 

가장 쉽게 new 키워드로 object 생산할 수 있는게 바로 날짜인데

자바스크립트에선 new Date() 이렇게 하면 date object 라는게 생성됩니다. 

그래서 instanceof로 부모 클래스가 누군지 검사할 수 있습니다. 

let 날짜 = new Date();
if (날짜 instanceof Date){
  console.log('참이에요')
}

이렇게 쓸 수 있고 이런 문법도 narrowing 역할을 할 수 있습니다.

이 변수가 Date()로 부터 생성된 object 자료인지, 아니면 다른 애로부터 생성된 자료인지 이런걸 구분가능하기 때문입니다.

 


자바스크립트는 함수를 만드는 방법이 2개 있습니다.

function 함수(){

}

let 함수2 = function (){

}

위는 함수 선언문,

밑은 함수 표현식이라고 부릅니다. 똑같이 함수만들 수 있는 문법입니다. 

'TIL' 카테고리의 다른 글

WIL 12주차  (0) 2023.01.24
TIL 12주 5일차 - Type script  (0) 2023.01.24
TIL 12주 3일차- Type script  (0) 2023.01.18
TIL 12주 2일차 - Type script 복습  (2) 2023.01.17
TIL 12주 1일차  (1) 2023.01.16