TS 숫자 구분자 및 보다 엄격한 클래스 속성 확인

개요


TypeScript 2.4는 식별자를 위한 맞춤법 수정 메커니즘을 구현합니다.비록 우리가 변수, 속성, 함수 이름을 약간 틀렸다 하더라도, TypeScript는 많은 상황에서 정확한 맞춤법을 제시할 수 있다.
TypeScript 2.7은 ECMAScript의 디지털 구분자 제안을 지원합니다.이 기능을 사용하면 숫자 사이에 밑줄을 사용할 수 있습니다 (_)숫자를 그룹화합니다. (쉼표와 점을 사용하여 숫자를 그룹화합니다.)

const worldPopulationIn2017 = 7_600_000_000;
const leastSignificantByteMask = 0b1111_1111;
const papayawhipColorHexCode = 0xFF_EF_D5;
숫자 구분자는 숫자의 글자 양의 값을 바꾸지 않지만, 그룹을 나누면 사람들이 숫자를 한 눈에 쉽게 읽을 수 있다.
이 구분 문자들은 2진법과 16진법에 똑같이 유용하다.

let bits = 0b0010_1010;
let routine = 0xC0FFEE_F00D_BED;
let martin = 0xF0_1E_
주의, 약간 상식적이지 않을 수 있습니다. js의 숫자는 신용카드와 전화번호가 적당하지 않다는 것을 나타냅니다. 이런 상황에서 문자열을 사용하는 것이 좋습니다.
target을 es2015에서 컴파일한 상기 코드로 설정하면 TypeScript는 다음과 같은 js 코드를 생성합니다.

const worldPopulationIn2017 = 7600000000;
const leastSignificantByteMask = 255;
const papayawhipColorHexCode = 16773077;

in 조작부호 세분화 및 정확한 instanceof


TypeScript 2.7은 유형 세분화에 대한 두 가지 변경 사항을 제공합니다. 즉, 유형 보호를 수행하여 보다 자세한 유형을 식별하는 능력입니다.
우선, instanceof 조작부호는 현재 구조 호환성에 의존하지 않고 계승 체인을 이용하여 instanceof 조작부호가 운행할 때의 행위를 더욱 정확하게 반영할 수 있다.이것은 복잡한 문제를 피하는 데 도움을 줄 수 있다. instanceof를 사용하여 구조적으로 비슷하지만 무관한 유형을 세분화할 때.
그 다음에 in 조작부호는 현재 유형 보호로 사용되고 명확한 성명이 없는 속성 이름을 세분화합니다.

interface A { a: number };
interface B { b: string };

function foo(x: A | B) {
    if ("a" in x) {
        return x.a;
    }
    return x.b;
}

보다 지능적인 대상 글자 추정


JS에는 사용자가 일부 속성을 무시하는 패턴이 있습니다. 나중에 사용할 때 그 속성의 값은undefined입니다.

let foo = someTest ? { value: 42 } : {};
이전에는 TypeScript에서 {value: number} 및 {}의 최상의 하이퍼 유형을 찾았는데 결과는 {} 였습니다.이것은 기술적으로 말하자면 정확하지만 결코 유용하지는 않다.
2.7 버전부터 TypeScript는 각 대상의 글꼴 형식을 규범화하고 각 undefined 형식의 속성에 선택할 수 있는 속성을 삽입하여 연합합니다.
위의 예에서foo의 가장 유형은 {value:number} | {value?:undefined}입니다.TypeScript의 세분화된 유형을 결합하여 우리는 더욱 표현적인 코드를 작성할 수 있고 TypeScript도 이해할 수 있다.다른 예:

// Has type
//  | { a: boolean, aData: number, b?: undefined }
//  | { b: boolean, bData: string, a?: undefined }
let bar = Math.random() < 0.5 ?
    { a: true, aData: 100 } :
    { b: true, bData: "hello" };

if (bar.b) {
    // TypeScript now knows that 'bar' has the type
    //
    //   '{ b: boolean, bData: string, a?: undefined }'
    //
    // so it knows that 'bData' is available.
    bar.bData.toLowerCase()
}
여기에서 TypeScript는 b 속성을 검사하여 bar의 유형을 세분화한 다음 bData 속성에 접근할 수 있습니다.

uniquesymbol 형식과 상수명 속성


TypeScript 2.7은 ECMAScript의symbols에 대해 더욱 깊이 있게 이해하고 그것들을 더욱 유연하게 사용할 수 있습니다.
하나의 수요가 매우 큰 용례는symbols를 사용하여 하나의 유형의 좋은 속성을 설명하는 것이다.예:

const Foo = Symbol("Foo");
const Bar = Symbol("Bar");

let x = {
    [Foo]: 100,
    [Bar]: "hello",
};

let a = x[Foo]; // has type 'number'
let b = x[Bar]; // has type 'string'
이를 통해 알 수 있듯이 TypeScript는 x가 기호인 Foo와 Bar를 사용하여 성명하는 속성을 추적할 수 있습니다. 왜냐하면 Foo와 Bar가 상수로 성명되기 때문입니다.TypeScript는 이를 활용하여 Foo와 Bar에 새로운 유형인 unique symbols를 가지게 했습니다.
unique symbols는 symbols의 하위 유형으로 Symbol () 또는 Symbol만 호출할 수 있습니다.for () 또는 명확한 유형의 주석으로 생성됩니다.그것들은 상량 성명과 읽기만 하는 정적 속성에만 나타나며, 존재하는 유니크symbols 형식을 인용하기 위해서는 typeof 조작부호를 사용해야 합니다.모든 유니크symbols에 대한 인용은 완전한 유일한 성명 신분을 의미한다.

// Works
declare const Foo: unique symbol;

// Error! 'Bar' isn't a constant.
let Bar: unique symbol = Symbol();

// Works - refers to a unique symbol, but its identity is tied to 'Foo'.
let Baz: typeof Foo = Foo;

// Also works.
class C {
    static readonly StaticSymbol: unique symbol = Symbol();
}
모든 유니크symbols는 완전히 독립된 신분을 가지고 있기 때문에 두 유니크symbols 유형은 값을 부여하고 비교할 수 없습니다.

const Foo = Symbol();
const Bar = Symbol();

// Error: can't compare two unique symbols.
if (Foo === Bar) {
    // ...
}
또 다른 가능한 용례는symbols를 연합 표시로 사용하는 것이다.

// ./ShapeKind.ts
export const Circle = Symbol("circle");
export const Square = Symbol("square");

// ./ShapeFun.ts
import * as ShapeKind from "./ShapeKind";

interface Circle {
    kind: typeof ShapeKind.Circle;
    radius: number;
}

interface Square {
    kind: typeof ShapeKind.Square;
    sideLength: number;
}

function area(shape: Circle | Square) {
    if (shape.kind === ShapeKind.Circle) {
        // 'shape' has type 'Circle'
        return Math.PI * shape.radius ** 2;
    }
    // 'shape' has type 'Square'
    return shape.sideLength ** 2;
}

더욱 엄격한 클래스 속성 검사


TypeScript 2.7은 클래스의 엄격한 속성 초기화 검사에 사용할 새로운 컴파일러 옵션을 도입했습니다.--strictProperty Initialization 로고를 사용하면 형식 관리자가 클래스에 설명된 모든 실례 속성을 검증합니다
  • undefined를 포함하는 유형이 있는지 여부
  • 명확한 초기값 설정 항목이 있습니다
  • 구조 함수에서 값이 명확하게 부여된다
  • --strictPropertyInitialization 옵션은 컴파일러 옵션 시리즈의 일부분으로 --strict 로고를 설정할 때 자동으로 사용됩니다.모든 다른 엄격한 컴파일러 옵션과 마찬가지로, 우리는 --strict를true로 설정하고, --strictProperty Initialization을false로 설정하여 엄격한 속성 초기화 검사를 선택적으로 종료할 수 있습니다.
    --strictNullCheck 로고 (--strict를 통해 직접 또는 간접적으로 설정) 를 설정하여 --strictProperty Initialization이 작용하도록 해야 합니다.
    이제 엄격한 속성 초기화 검사를 살펴보자.--strictpropertyinitialized 로고를 사용하지 않으면 다음 코드 형식을 검사하면 되지만 실행할 때 TypeError 오류가 발생합니다.
    
    class User {
      username: string;
    }
    
    const user = new User();
    
    // TypeError: Cannot read property 'toLowerCase' of undefined
    const username = user.username.toLowerCase();
    실행 중 오류가 발생한 이유는username 속성 값은undefined입니다. 이 속성에 대한 값이 없기 때문입니다.따라서 toLowerCase() 메서드에 대한 호출이 실패했습니다.
    - strictpropertyinitialize를 사용하면 형식 검사기에서 오류가 발생합니다.
    
    class User {
      // Type error: Property 'username' has no initializer
      // and is not definitely assigned in the constructor
      username: string;
    }
    다음은 네 가지 다른 방법을 살펴보자. 사용자 클래스를 정확하게 입력하여 유형 오류를 없앨 수 있다.

    솔루션 1: 정의 허용


    형식 오류를 없애는 방법 중 하나는 username 속성에 undefined를 포함하는 형식을 제공하는 것입니다.
    
    class User {
      username: string | undefined;
    }
    
    const user = new User();
    현재username 속성은undefined의 값을 저장하는 데 완전히 유효합니다.그러나, username 속성을 문자열로 사용하려면, 우선 undefined 값이 아닌 문자열을 실제적으로 포함해야 합니다. 예를 들어typeof를 사용해야 합니다.
    
    // OK
    const username = typeof user.username === "string"
      ? user.username.toLowerCase()
      : "n/a";

    솔루션 2: 명시적 속성 초기화


    유형 오류를 없애는 또 다른 방법은username 속성에 현식 초기화를 추가하는 것입니다.이러한 방식으로 속성은 문자열 값을 즉시 저장하고 뚜렷한 undefined를 저장하지 않습니다.
    
    class User {
      username = "n/a";
    }
    
    const user = new User();
    
    // OK
    const username = user.username.toLowerCase();

    해결 방안 3: 구조 함수를 사용하여 값을 부여합니다.


    아마도 가장 유용한 해결 방안은username 매개 변수를 구조 함수에 추가한 다음username 속성에 분배하는 것이다.이렇게 하면 User 클래스의 인스턴스를 구성할 때마다 호출자는 사용자 이름을 매개 변수로 제공해야 합니다.
    
    class User {
      username: string;
    
      constructor(username: string) {
        this.username = username;
      }
    }
    
    const user = new User("mariusschulz");
    
    // OK
    const username = user.username.toLowerCase();
    클래스 필드에 대한 현식 값을 삭제하고public 수식자를 username 구조 함수 파라미터에 추가하여 사용자 클래스를 간소화할 수 있습니다. 아래와 같습니다.
    
    class User {
      constructor(public username: string) {}
    }
    
    const user = new User("mariusschulz");
    
    // OK
    const username = user.username.toLowerCase();
    엄격한 속성 초기화는 구조 함수의 모든 가능한 코드 경로에서 모든 속성을 명확하게 분배해야 한다는 것을 주의하십시오.따라서 다음 코드 형식이 올바르지 않습니다. 왜냐하면 어떤 경우에는username 속성을 초기화되지 않은 상태로 지정하기 때문입니다.
    
    class User {
      // Type error: Property 'username' has no initializer
      // and is not definitely assigned in the constructor.
      username: string;
    
      constructor(username: string) {
        if (Math.random() < 0.5) {
          this.username = username;
        }
      }
    }

    솔루션 4: 명확한 할당 단언


    만약 클래스 속성이 현식 초기화도 없고 undefined 형식도 없다면 유형 검사자는 구조 함수에서 이 속성을 직접 초기화해야 한다.그렇지 않으면 엄격한 속성 초기화 검사가 실패합니다.만약 우리가 도움말 방법에서 속성을 초기화하거나 의존항을 프레임워크에 주입하여 속성을 초기화하기를 원한다면 이것은 문제가 있다.이러한 상황에서 우리는 반드시 명확한 가치 부여 단언을 해야 한다 (!)이 속성의 선언에 추가:
    
    class User {
      username!: string;
    
      constructor(username: string) {
        this.initialize(username);
      }
    
      private initialize(username: string) {
        this.username = username;
      }
    }
    
    const user = new User("mariusschulz");
    
    // OK
    const username = user.username.toLowerCase();
    username 속성에 명확한 값 부여 단언을 추가하면 형식 관리자에게 username 속성을 초기화하기를 기대합니다. 설령 자신이 이 점을 감지할 수 없다 하더라도.현재 우리의 책임은 구조 함수가 되돌아온 후에 속성을 명확하게 부여하는 것을 확보하는 것이므로 반드시 조심해야 한다.그렇지 않으면 사용자 이름 속성이 뚜렷하게 undefined되거나 실행할 때 TypeError 오류가 발생할 수 있습니다.

    현식 부치 단언


    비록 우리는 유형 시스템을 더욱 표현력 있게 하려고 시도하지만, 때로는 사용자가 TypeScript보다 유형을 더 잘 이해하는 것을 안다.
    위에서 언급한 바와 같이 현식 부여 단언은 새로운 문법으로 TypeScript의 속성이 명확하게 부여될 것이라고 알려준다.그러나 클래스 속성에서 그것을 사용하는 것 외에 TypeScript 2.7에서 변수 성명에서 그것을 사용할 수 있습니다!
    
    let x!: number[];
    initialize();
    x.push(4);
    
    function initialize() {
        x = [0, 1, 2, 3];
    }
    만약 우리가 x 뒤에 느낌표를 붙이지 않았다면, TypeScript는 x가 초기화된 적이 없다고 보고할 것이다.그것은 초기화를 지연시키거나 다시 초기화하는 장면에서 사용하기 매우 편리하다.
    이상은 TS 숫자 구분자와 더욱 엄격한 클래스 속성 검사에 대한 상세한 내용입니다. 더 많은 TS에 관한 자료는 저희 다른 관련 글에 주목하세요!

    좋은 웹페이지 즐겨찾기