TypeScript v3.주요 변경 사항 복습

37344 단어 TypeScripttech
며칠 전, TSv42가 발매되었기 때문에 이 기회를 빌려 v3 각 이터레이션의 주요 변경 사항을 복습하고 싶습니다.
다음에 v4의 변경점과 추가점을 보고 싶습니다.

v3.x당 주요 기능 변경


v3.0

  • tuple형 강화(파라미터 목록과 통합)
  • // Both `y` and `z` are optional here.
    function foo(x: boolean, y = 100, z?: string) {
        // ...
    }
    
    foo(true);
    foo(true, undefined, "hello");
    foo(true, 200);
    
    // `rest` accepts any number of strings - even none!
    function foo(...rest: string[]) {
        // ...
    }
    
    foo();
    foo("hello");
    foo("hello", "world");
    
  • JSX의defaultProops 지원
  • function Greet({ name = "world" }: Props) {
        return <div>Hello ${name.toUpperCase()}!</div>;
    }
    
  • 프로젝트 간 참조 지원
  • unknown형의 추가
  • v3.1

  • tupple형과aray형을 처리할 때mapped type의 개선
  • type Stringify<T> = {
        [K in keyof T]: string
    };
    
    declare function stringifyAll<T extends unknown[]>(...elements: T): Stringify<T>;
    
    let stringyCoordinates = stringifyAll(100, true);
    
    // No errors!
    let first: string = stringyCoordinates[0];
    let second: string = stringyCoordinates[1];
    
    let len: 2 = stringyCoordinates.length
    // Type 'string' is not assignable to type '2'.
    
    stringyCoordinates.forEach(x => console.log(x));
    // Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
    
    이전에는 이런 상황에서stringy Coordinates가 가진length,forEach 등의 속성이string으로 판정되었다.
  • 속성을 함수에서 간단하게 만들기 위해
  • export const FooComponent => ({ name }) => (
        <div>Hello! I am {name}</div>
    );
    
    FooComponent.defaultProps = {
        name: "(anonymous)",
    };
    

    v3.2

  • 히트네릭스의 대상 스프레드시트
  • let person = { name: "Daniel", location: "New York City" };
    
    // My secret revealed, I have two clones!
    let shallowCopyOfPerson = { ...person };
    let shallowCopyOfPersonWithDifferentLocation = { ...person, location: "Seattle" };
    TypeScript does a pretty good job here when it has enough information about the type. The type system closely tries to model the behavior of spreads and overwrites new properties, tries to ignore methods, etc. But unfortunately up until now it wouldn't work with generics at all.
    
    function merge<T, U>(x: T, y: U) {
        // Previously an error!
        return { ...x, ...y };
    }
    
    // Returns '{ name: string, age: number, greeting: string } & T'
    function foo<T>(obj: T) {
        let person = {
            name: "Daniel",
            age: 26
        };
    
        return { ...person, greeting: "hello", ...obj };
    }
    
    이전에merge와 같은 함수는 틀렸지만 개선되었다.
  • bind,call,apply 개선형 추론
  • 을 통해
    function foo(a: number, b: string): string {
        return a + b;
    }
    
    let a = foo.apply(undefined, [10]);              // error: too few argumnts
    let b = foo.apply(undefined, [10, 20]);          // error: 2nd argument is a number
    let c = foo.apply(undefined, [10, "hello", 30]); // error: too many arguments
    let d = foo.apply(undefined, [10, "hello"]);     // okay! returns a string
    
    bind,call,apply의 유형 추론을 개선하여 이전에 오류 검출이 불가능했던 유형을 검출할 수 있도록 한다.

    v3.3

  • Union형 개선
  • interface A {
        aProp: string;
        commonProp: string;
    }
    
    interface B {
        bProp: number;
        commonProp: number
    }
    
    type Union = A | B;
    
    declare let x: Union;
    
    x.aProp; // error - 'B' doesn't have the property 'aProp'
    x.bProp; // error - 'A' doesn't have the property 'bProp'
    x.commonProp; // okay! Both 'A' and 'B' have a property named `commonProp`.
    
    Union의 공통 속성에 액세스할 수 있음
    type Fruit = "apple" | "orange";
    type Color = "red" | "orange";
    
    type FruitEater = (fruit: Fruit) => number;     // eats and ranks the fruit
    type ColorConsumer = (color: Color) => string;  // consumes and describes the colors
    
    declare let f: FruitEater | ColorConsumer;
    
    f("orange"); // It works! Returns a 'number | string'.
    
    f("apple");  // error - Argument of type '"apple"' is not assignable to parameter of type '"orange"'.
    
    f("red");    // error - Argument of type '"red"' is not assignable to parameter of type '"orange"'.
    
    도 함수라고 할 수 있지만 공통 유형만 전달할 수 있다.
  • 대규모 프로젝트 대응
  • 복합 프로젝트 가져오기라는 새로운 기능을 통해 대규모 프로젝트를 작은 단위로 분할하여 TS의 은혜를 해치지 않고build를 신속하게 진행할 수 있다.

    v3.4

  • incremental 표지
  • TS의 개발에서 원본이 바뀔 때 구축 시간이 짧은 것이 중요하다.
    지금까지는 워치 마크를 사용해 변경의 영향을 받은 곳만 재구성했다.
    incremental 로고는 지난번에 컴파일된 정보를 저장하고 이 정보를 사용하여 유형 검사에 필요한 비용을 최소화하는 방법을 지정합니다.
  • readOnly의 배열과 원조형
  • function foo(arr: ReadonlyArray<string>) {
        arr.slice();        // okay
        arr.push("hello!"); // error!
    }
    
    function foo(pair: readonly [string, string]) {
        console.log(pair[0]);   // okay
        pair[1] = "hello!";     // error
    }
    

    v3.5

  • omit 가져오기
  • type Person = {
        name: string;
        age: number;
        location: string;
    };
    
    type QuantumPerson = Pick<Person, "location">;
    
    // equivalent to
    type QuantumPerson = {
        name: string;
        age: number;
    };
    
    특정 속성을 제외한 유형을 만듭니다.
  • Union형 과잉 속성에 대한 유형 검사 개선
  • type Point = {
        x: number;
        y: number;
    };
    
    type Label = {
        name: string;
    };
    
    const thing: Point | Label = {
        x: 0,
        y: 0,
        name: true
    };
    
    이전에는 name이 bool임에도 불구하고 오류가 발생하지 않았지만 오류가 발생했습니다.

    v3.6

  • 균형기 및 생성기에 대한 엄격한 검사 가능
  • function* foo() {
        if (Math.random() < 0.5) yield 100;
        return "Finished!"
    }
    
    let iter = foo();
    let curr = iter.next();
    if (curr.done) {
        // TypeScript 3.5 and prior thought this was a 'string | number'.
        // It should know it's 'string' since 'done' was 'true'!
        curr.value
    }
    
    전통적으로 생성기를 사용하는 상황에서eld값에 따른 값인지 되돌아오는 값인지 확정할 수 없다.
    function* bar() {
        let x: { hello(): void } = yield;
        x.hello();
    }
    
    let iter = bar();
    iter.next();
    iter.next(123); // oops! runtime error!
    
    또한 생성기는 Yeld의 유형을ny로 추정할 수 있으나 수정되었습니다.

    v3.7

  • optional chaining
  • let x = foo?.bar.baz();
    
    null이나undefined의 경우 정지 처리를 쓸 수 있습니다.
    foo가null 또는undefined라면 x는undefined입니다.
  • Nullish Coalescing
  • let x = foo ?? bar();
    
    null이나undefined의 경우 기본값으로 되돌릴 수 있습니다.
    foo가null이나undefined라면 x는bar()의 반환값입니다.
    let y = hugu || 0.5
    
    ||||를 사용할 때 hugu가 0이라도 y는 0.5이다.
    이런 잘못된 온상을 하지 마세요??제작됐습니다.
  • Assertion Functions
  • function multiply(x, y) {
        assert(typeof x === "number");
        assert(typeof y === "number");
    
        return x * y;
    }
    
    assert에 전달된 매개 변수의 조건이 가짜라면
    AssertionError를 던져 처리에 실패했습니다.

    v3.8

  • 클래스 개인 필드 지원
  • class Person {
        #name: string
    
        constructor(name: string) {
            this.#name = name;
        }
    
        greet() {
            console.log(`Hello, my name is ${this.#name}!`);
        }
    }
    
    let jeremy = new Person("Jeremy Bearimy");
    
    jeremy.#name
    //     ~~~~~
    // Property '#name' is not accessible outside class 'Person'
    // because it has a private identifier.
    
    개인 필드를 지원하고 클래스 밖에서 사용하면 오류가 발생합니다.
  • Top-Level await
  • const response = await fetch("...");
    const greeting = await response.text();
    console.log(greeting);
    
    // Make sure we're a module
    export {};
    
    async가 추가된 함수에서만 await를 사용할 수 있습니다
    모듈의 맨 위에서 사용할 수 있습니다.

    v3.9

  • Promise.all형 추론의 개선
  • interface Lion {
        roar(): void
    }
    
    interface Seal {
        singKissFromARose(): void
    }
    
    async function visitZoo(lionExhibit: Promise<Lion>, sealExhibit: Promise<Seal | undefined>) {
        let [lion, seal] = await Promise.all([lionExhibit, sealExhibit]);
        lion.roar(); // uh oh
    //  ~~~~
    // Object is possibly 'undefined'.
    }
    
    특히 null과undefined를 함께 사용할 때 때로는 추론의 결과가 정확하지 않지만 수정되었다.

    좋은 웹페이지 즐겨찾기