제로초강의_타입스크립트1

nevermind·2023년 12월 2일
0

typescript

목록 보기
11/12

ts

  • js의 변수, 매개 변수, 리턴값3개만 type을 다 붙여놓으면 그것이 ts
    • 변수는 const a:string = ‘5’ 타입은 꼭 소문자여야함!
    • 배열 표기법
      • const arr : string[] =[’123’,’456’]
      • const arr2 : Array[123,456] (<>꺽쇠는 제네릭)
      • 튜플은 고정적인 값
        • const arr3:[number,string] = [123,’aaa’] 그 이상 추가되면 에러발생
    • boolean타입
      • 타입은 최대한 정확하게 하는게 제일 좋은
        • const f : boolean = true로 무조건 true값을 받는다면 boolean일 필요가 없고 const f:true = true로 정확한 원시값 타입으로 둘 수 있음
    • any는 js가 됨
    • 매개변수는 const add:(x:number, y:number) ⇒ number =(x,y) ⇒ x+y; (type을 지웠을때도 말이 되는 js코드여야함)
  • 타입선언방법
    • interface 를 통해서 함수의 타입을 정의해줄 수 있음
      interface Add {
      	(x:number, y:number): number
      }
  • 타입 추론을 적극 이용하자
    • 타입은 최대한 정확하게 하는 것이 중요하다 *
      • const a = ‘5’;
      • const a: string = ‘5’;로 하면 타입을 더 부정확하게 함
        • ‘5’라는 타입이 있었는데 string이라는 더 넓은 타입으로 바뀌게 함
        • ts가 똑똑하면서 틀리기도 함
        • 추론이 잘되면 추론에 맡기고 안되면 내가 직접 입력
  • js 변환시 사라지는 부분을 기억하자
    • 타입이 사라지는 것을 명확하게 알아야한다
    • 콜론, 타입, 인터페이스, 제네릭
      type Add () => number;
      interface Minus {}
      Array<string>
      const f:true = true
    • 심화
      function add(x:numer, y: number): number;
      //js에서는 위에 사라짐
      function add(x,y){
      	return x+y
      }
      • 같은 함수 add가 중복으로 쓰이면 원래 안되지만 타입만 나오고 아래는 선언되어 있는 케이스 존재함

        let aa =123;
        aa = 'hello' as unknown as number;
        //js에서는 as도 사라짐
      • number을 as를 사용해서 억지로 unknown 타입으로 바꿔줌

  • never 타입과 느낌표(non-null assertion)
    • never타입
      • never타입은 empty타입과 같음

      • 집합에 어떤 값도 없기에 any타입을 포함하여 어떤 값도 가질 수 없다.

      • 그래서 never타입은 점유할 수 없는, 바닥타입이라고 불린다

        declare const any: any
        const never: never = any // ❌ 'any' 타입은 'never'타입에 할당할 수 없다.
      • 바닥타입이다. 바닥타입이란 ts계층 트리에서 가장 아래에 위치하여 어떤 값도 가질 수 없음을 의미

      • 빈 배열은 never이기에 꼭 타입을 지정해줘야한다

        const arr:string[] = []
      • 허용할 수 없는 함수 매개변수에 제한을 가한다

        function unknownColor(x: never): never {
            throw new Error("unknown color");
        }
        
        type Color = 'red' | 'green' | 'blue';
        
        function getColorName(c: Color): string {
            switch(c) {
                case 'red':
                    return 'is red';
                case 'green':
                    return 'is green';
                default:
                    return unknownColor(c); // 에러 없이 동작
            }
        }
    • 느낌표
      • null이나 undefined가 아님을 확신할때
        const head = 
        document.querySelector('#head')!
        
        head가 바뀔 수 있음
        • !는 js에서 사라짐

        • 그러나 비추, 절대적일 수 없다

          대신 아래처럼 써라
          
          const head = 
          document.querySelector('#head')
          
          if(head){
          	head.innerHTML = 'hello';
          }
  • 원시 래퍼 타입, 템플릿 리터럴 타입, rest, 튜플, enum
    • 타입에 값을 지정해줬을때, 그 타입을 값처럼 사용 가능하다 (타입 정교하게 만드는 작업)
      type World = 'world';
      const a:World = 'world'; //자동완성됨
      
      const b = `hello ${a}`;
      
      //type Greetin = "hello world"가 됨
      type Greeting = `hello ${World}`;
      
      //현실적으로 쓸 때
      type World = "world" |"around"
      type Greeting = `hello ${World}`
      const c: Greeting = `hello ...` 
      //여기서 hello world나 hello around로 타입 추천이 됨
      
    • rest
      function rest(a,...args: string[]){
      	console.log(a, args); //1, [2,3]
      }
      rest('1','2','3')
    • 튜플타입
      const tuple:[string, number] = ['1',1];
      tuple[2]=2 ; //하면 에러, 3번째 자리에 고정적인 값이 없기에
      
      tuple.push('hello') //대신 이거는 됨
    • enum
      const enum E{
      	Up = 3,
      	Down = 4,
      	Left = 6,
      	Right = 'hello',
      } // 위 식은 js에서 사라짐
      const a = E.Up; //a=3 나옴
      const b = E.Right //b=5 나옴
      
      //enum이 아닌 객체 형식
      const E = {
        Up : 0,
      	Down : 1,
      	Left : 2,
      	Right : 3,
      } as const
      //위 식은 as 뒷부분부터 js에서 사라짐
      //js에 없애고 싶으면 enum 남기게 하고 싶다면 객체형식으로 쓰기
      // 남길지 안남길지 모르겠다면 남기는 것 추천
      // ts가 은근 모자람, 객체 형식에 숫자를 지정해서 넣었는데 
      // 타입추론을 정확한 숫자가 아닌 number로 받음, 추론을 못하면 내가 직접 타입을 줘야한다
      const E:{Up : 0,	Down : 1,	Left : 2,	Right : 3,} = {
        Up : 0,
      	Down : 1,
      	Left : 2,
      	Right : 3,
      }
      //이렇게 쓸 수도 있지만,위에 써놓은 것처럼 as const로 상수로 지정하면 됨
      //상수로 지정하면 아래 사진처럼 readonly로 나옴
      Untitled
    • keyof
      const obj = {a:'123', b:'hello', c:'world'};
      type Key = keyof typeof obj;
      //js값은 타입으로 쓸 수가 없음
      //키들만 뽑아내고 싶다면
      //Key는 "a"|"b"|"c"로 나옴
      
      type Key = typeof obj[keyof typeof obj;
      //value의 타입만 뽑아내고 싶다면,
      //Key는 string|string|string
      Untitled
  • type과 interface차이 ? 간단하게 하고 싶으면 type, 상속받고 implement구현, 객체 지향 프로그래밍 하고 싶으면 interface
  • union === |
    • 또는

      func add(x:string|number, y: string|number):string|number {return x+y}
      
      add(1,2);
      add('1','2');
      add(1,'2');
      
      //문제 생김
      const result: string|number = add(1,2);
      //add(1,2)일때 결과는 number이지만 result는 string|number로 보이게 된다.
      result.charAt();//charAt는 문자열에 사용되기에 타입에러가 생김
      
      //add처음 타입을 잘 잡아야한다.
      //맞는 말인 것 같아도 줄줄이 타입에러날 수 있음
  • intersection(&)
    type A = string & number // 안됨
    type A = {hello: 'world'} &{zero:'cho'};
    const a:A = {hello:'world', zero:'cho'};
    const a:A = {hello:'world'};//타입에러
    //& 둘다 만족되어야함
    //모든 속성이 다 있어야한다
    
    type A = {hello: 'world'} | {zero:'cho'};//이것도 가능
    const a:A = {hello:'world', zero:'cho'};
    //| (유니언) 하나만 있어도 된다
  • type
    • 확장의 개념으로 쓸 수 있음

      type Animal = {breath: true};
      type Mammals = Animal & {breed:true};
      type Human = Mammals & {think: true};
      
      const zero:Human = {breath: true, breed:true, think:true};
      //3개 다 되어야함
  • interface
    • 중복으로 써도 됨

      Untitled

    • 확장이 쉬워짐(추가)

  • 큰타입, 작은 타입
    • 좁은 타입에서 넓은 타입으로 대입은 가능

      type A = stirng|number; //큰 타입
      type B = string; //작은 타입
      type C = string&number //없는 타입이지만 여기서 제일 작은 타입임
      
      type A = {name: string};
      type B = {age: string};
      type C = {name: string, age:string}; //구체적일수록 좁은 타입임 === A & B
      type AB = A|B //제일 넓은 타입
      
      const c : C = {name : 'zerocho', age: 29}
      const ab : AB = c;
      //작은 타입에서 넓은 타입으로 넣을 수 있음

Untitled

type C = {name: string, age:string}; 
type AB = A|B

const ab:AB  = {name:'zero'};
const c: C = {name:'zero', age:29, married:false}; 
//C타입보다 {name:'zero', age:29, married:false}가 더 좁은데
//좁은 타입을 넓은 타입에 넣었는데 에러가 뜸
//객체 리터럴 검사라는 것 떄문에 에러 (잉여속성 검사라는 것때문에 에러가 생김)

const obj = {name:'zero', age:29, married:false}; //이렇게 변수를 빼주면 에러 사라짐
const c: C = obj; 
  • 잉여속성 검사 특성
    • 객체 리터럴을 바로 대입해서 쓸 때 잉여속성검사가 들어간다

      const c :C = {name:'zero', age:29, married:false}; //에러
      
      const obj = {name:'zero', age:29, married:false}; //이렇게 변수를 빼주면 에러 사라짐
      const c: C = obj; 
  • void 타입
    • return 값이 void(여기에만 값을 넣지못함) === 함수가 어떤 값을 반환하지 않겠다

      function a():void {
      	return 3;
      }
      //void함수는 return값을 넣으면 안되는 타입
      //대신 undefined는 됨
      //null은 안됨
      function a():void {
      	return
      }
    • 매개변수가 void 함수=== return 값을 사용하지 않겠다 ===실제 return값이 뭐든 상관하지 않겠다

      function a(callback: ()=>void) {
      }
      
      a(()=> {
      	return '3';
      });
      //이렇게는 가능
    • method로 선언할때 void (아래와 같을때는 가능)=== return 값을 사용하지 않겠다

      interface Humna {
      	talk: ()=>void;
      }
      
      const human:Human {
      	talk() {return 'abc';}
      }
  • 예제
declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;
// declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
forEach([1, 2, 3], el => {target.push(el)});
forEach([1, 2, 3], el => target.push(el));

interface A {
    talk: () => void;
}
const a: A = {
    talk() { return 3; }
}
const b = a.talk(); //예상으로는 3이 나와야 하지만 Js에서 결과를 무시해버림

const b = a.talk() as unkown as number //내가 강제로 바꿀 수 있음

쉽게 말해, void 반환 타입은 함수나 메서드가 어떠한 값을 반환하지 않음을 명시적으로 나타내는 것이며, 이것은 코드를 읽는 사람에게 함수의 동작을 더 명확하게 전달하고, TypeScript가 타입 관련 오류를 잡아내도록 도와줍니다.

  • unknown
    • 타입 잘 모를때 씀
  • any
    • 타입선언 패스
  • 타입가드
    type B = { type: 'b', bbb: string };
    type C = { type: 'c', ccc: string };
    type D = { type: 'd', ddd: string };
    type A = B | C | D;
    function typeCheck(a: A) {
      if (a.type === 'b') {
        a.bbb;
      } else if (a.type === 'c') {
        a.ccc;
      } else {
        a.ddd;
      }
    }
    //속성으로 구분하는 법
    
    function typeCheck(a: B|C|D) {
      if ('bbb' in a) { //bbb가 있는 a를 찾으면 a:B로 타입 추론됨
        a.bbb;
      } else if (a.type === 'c') {
        a.ccc;
      } else {
        a.ddd;
      }
    }
    • is
      • 타입을 구분해주는 커스텀함수를 우리가 직접 만들 수 있음

      • return 타입에 is가 들어있는 애들은 커스텀 타입가드 함수임

        interface Cat { meow: number }
        interface Dog { bow: number }
        function catOrDog(a: Cat | Dog): a is Dog {
          if ((a as Cat).meow) { return false }
          return true;
        }
        const cat: Cat | Dog = { meow: 3 }
        if (catOrDog(cat)) { //if문 안에 써야 정확한 타입이 뭔지
            console.log(cat.meow);
        }
        if ('meow' in cat) {
            console.log(cat.meow);
        }
  • 4.8버전 업데이트 내용 {}와 Object
    • {}, Object 모든 타입임(null, undefined 제외)
    • unkown타입은 {} | null | undefined 모든 타입이됨
      const z : unknown = 'hi';
      if(z){ //true 타입이기에
      	z //{}타입으로 받아들임
      } else {
      	z;
      }
  • 자주 쓰이는 것들
    • Readonly
    • 인덱스드 시그니쳐
      type A = {a:string, b: string ...}
      //모든 속성이 다 문자열이길 바랄떄
      type A = { [key:string] : string }
      //어떤 키든 상관없이 string
      
      //key를 줄여놓을때
      type B = 'Human' | 'Mammal' | 'Animal'; //제한 걸 수 있음
      type A = { [key in B] : number }
      const aa : A = {Human:123, Mammal:123}
    • inerface는 |이나 & 안됨
  • 옵셔널, 제너릭 기본
    • 제네릭
      • 타입은 나중에 정할래, 타입을 변수처럼 정하는 것

        function add<T>(x:T, y:T):T {
        	return x+y;
        }
        
        add(1,2); //3
        add('1','2');//'12'
        add(true, false) // 이것도 됨 이걸 제한하고 싶다면?
        //function add<T extends number|string >(x:T, y:T):T {
        	return x+y;
        }
        extends로 제한한다
        
        //제네릭은 선언할 때말고 사용할때 타입이 정해짐
        // <T extends abstract new (...args: any) => any> // 생성자 타입,
        //제한 거는 것에 제한이 없게 하고 싶으면 any로 사용
  • 기본값 타이핑
    • 리액트 설정시

      const add = <T>(x:T, y:T) => ({x,y})
      //<T>하면 태그로 인식해서 에러뜰 수도 있으니 <T: unknown>
    • 객체 타입 지정시

      const a = (b: {children: string} = {children : 'zero'} ) => {}
      //위와 같이 써야함
profile
winwin

0개의 댓글