Archive

[TS] Private / Static / Generic 등

manon_e 2022. 1. 5. 16:39
반응형

 

 

 

     


     

     

     

     

     

     


    Rest parameter

     

     

     rest parameter는 항상 [ ] 안에 담겨오기 때문에 타입지정도 array처럼 해준다.

     

    function Plus(...a: number[]) {
      console.log(a);
    }
    
    Plus(1, 2, 3, 4, 5);

     

     

     

     


     

     

     

     

     

    Destructuring

     

     

    1. parameter에 object처럼 타입지정.

    2. type 키워드로 따로 만들어서 지정.

     

    // Object
    let person = { student: true, age: 20 };
    
    // 파라미터에 object처럼 타입지정
    function 함수({ student, age }: { student: boolean; age: number }) {
      console.log(student, age);
    }
    함수({ student: true, age: 20 });
    
    
    // 2. type 키워드
    type obj5 = {
      student: boolean;
      age: number;
    };
    // Array
    type Check2 = (number | string | boolean)[];
    
    function 연습2([a, b, c]: Check2) {
      console.log(a, b, c);
    }
    
    연습2([40, "wine", true]);

     

     

     

     


     

     

     

     

    Private / Protected

     

     

    class안에서 public 키워드 사용하면 그 속성은 아무데서나 수정 가능하다.

    ( 필드값 같은걸 그냥 만들면 public이 몰래 왼쪽에 부여되므로 붙이든 안붙이든 사실 똑같..)

    * public 키워드는 class내의 prototype 함수에도 붙일 수 있다.

     

     

    🔻 private 키워드 붙이면 무조건 class { } 중괄호 안에서만 수정 및 사용이 가능하다.

    ( class로 부터 생성된 자식 object 에서도 사용 불가능 )

    외부에서 실수로 수정하지 않도록 지켜주고싶은 중요한 변수나 속성에 안전장치로 private 붙여준다.

     

     

    > class 밖에서 죽어도 수정하고 싶으면?

       private 속성을 수정하는 함수를 class안에 만들어서 함수를 실행한다.

     

     

    class User {
      public name :string;
      private familyName :string;
    
      constructor(){
        this.name = 'kim';
        let hello = this.familyName;
      }
      changeSecret(){
        this.familyName = 'park';
      }
    }
    
    let 유저1 = new User();
    유저1.familyName = 'park';  //에러남
    유저1.changeSecret()        //가능

     

     

     

     

    🔻  Protected : private인데 약간 보안을 해제하고 싶을 때

    1. private랑 같은데

    2. extends 된 class 안에서도 사용가능하다. (Userd의 자식은 사용 불가능. extends된것만!!)

     

    class User {
      protected x = 10;
    }
    
    class newUser extends User {
      changeNum() {
        this.x = 20;
      }
    }

     

     

     

     

     


     

     

     

     

     

     

     

    Static

     

     

     class { }안에 들어가는 변수, 함수 등은 (필드값은 ) 전부 instance에 부여된다.

     이걸 바꿔서 class에 직접 변수나 함수를 부여하고 싶을 때 static 키워드를 붙여준다.

     

     

    🤷🏻‍♀️  언제씀?

      : 주로 class안에 간단한 메모를 하거나, 기본 설정값 입력

        instance에서 사용할 필요가 없는 변수들을 만들어놓고 싶을 때 사용한다.

     

    class User1 {
      x = 10;
    }
    
    let user1 = new User1();
    User1.x;   //불가능
    user1.x    //가능
    class User1 {
      static x = 10;
    }
    
    let user1 = new User1();
    User1.x;   //가능
    user1.x    //불가능

     

     

    private, protected, public과 함께 사용가능하다.

    class User4 {
      //필드값은 모든 User4의 자식에게 물려주는 속성이지만, static 붙은 x,y는 자식들은 쓸수없다.
      //User4.x 이런식으로만 접근가능하다.
      private static x = 10;
      //x는 class내부에서만 수정가능하다.
      public static y = 20;
      //y는 내외부 상관없이 수정가능하다.
    }

     

     

     

     


     

     

     

     

     

    Import

     

     

     타입변수도 ES6 import export 문법 그대로 사용해서 다른파일에서 사용 가능하다.

     

    (a.ts)
    
    export type Name = string | boolean;
    export type Age = (a :number) => number;
    (b.ts)
    
    import {Name, Age} from './a'
    let 이름 :Name = 'kim';
    let 함수 :Age = (a) => { return a + 10 }

     

     

     

    (참고) namespace

     : 이전엔 중요한 타입정의들을 다른 파일들에서 쓰고 싶으면 안전하게 namespace 안에 써서 export 해줬다. 

    (a.ts)
    
    namespace MyNamespace {
      export interface PersonInterface { age : number };
      export type NameType = number | string;
    }
    (b.ts)
    
    /// <reference path="./a.ts" />
    
    let 이름 :MyNamespace.NameType = '민수';
    let 나이 :MyNamespace.PersonInterface = { age : 10 };
    
    type NameType = boolean; //사용 가능
    interface PersonInterface {} //사용 가능

    그러면 ts 파일은 <reference/> 라는 태그를 이용해서 다른 파일을 import해올 수 있는데

    그럼 이제 그 파일에 있던 namespace를 사용가능하다.

    네임스페이스명.타입명 

    이렇게 쓰면 다른 파일에 있던 타입변수를 자유롭게 쓸 수 있다. 

     

     

     

     

     


     

     

     

     

     

    Generic

     

     

    [서론]

    타입스크립트는 타입을 알아서 변경해주지 않는다.

    (숫자가 return되면 'number 타입임다!' 이런거 안됨)

     

    function 함수3(x: unknown[]) {
      return x[0];
    }
    
    let a = 함수3([4, 2, 3]);
    console.log(a+1);    //에러

    그래서 이런경우도 에러가 발생한다.

    a는 type지정이 안됬으므로, unknown타입이고 그래서 a+1같은 연산도 에러가 발생한다.

    불확실한 unknown, any, union 타입을 입력하면 나오는 값도 동일하고 이때문에 에러가 발생한다.

    해결은 narrowing을 하면되는데 구찮,,

    이럴 때 generic을 사용한다.

     

    🔻 Generic : 타입파라미터 문법

        애초에 타입을 파라미터로 함수에 미리 입력한다.

        그러면 원하는 곳에 가변적으로 타입지정이 가능하다.

        유연성과 타입의 안전성을 동시에 지킬 수 있다.

     

    function 함수3<T>(x: T[]): T {
      return x[0];
    }
    
    let a = 함수3<number>([4, 2, 3]);
    //function 함수3 (x: number[]): number {
    //  return x[0];
    //}
    let b = 함수3<string>(["kim", "park"]);

     함수에 <> 이런 괄호에 파라미터를 또 입력할 수 있는데, 여기안엔 타입만 입력할 수 있다. (타입 파라미터 문법)

     a에는 <number>를 입력했으므로 function 함수3 (x : number[]):number { } 와 같다.

     

     

     

     

    ✔️  <T>에 number말고 다른것도 들어갈 수 있기때문에 연산에서는 에러가 발생.

    function 함수3<T>(x: T[]): T {
      return x - 1;   //에러
    }
    
    let a = 함수3<number>([4, 2, 3]);

     

    해결 ) narrowing하거나 <T>에 넣을 수 있는 타입 미리 제한한다. (constraints : extends 사용)

    function 함수3<T extends number>(x: T) {
      return x - 1;
    }
    
    let a = 함수3<number>(100);

     

     

       * interface로 커스텀한 타입도 extends 가능

    interface lengthCheck {
      length: number;
    }
    function 함수4<MyType extends lengthCheck>(x: MyType) {
      return x.length;
    }
    
    let c = 함수4<string>("hello");

     

      * class에서 Generic사용

    class Person3<T> {
      name;
      constructor(a2: T) {
        this.name = a2;
      }
    }
    let a2 = new Person3<string>("어쩌구");
    console.log(a2.name);

     

     

     

     

     

     

    반응형