compileOptions - strict

Seulyi Yoo·2022년 7월 15일
0

TypeScript

목록 보기
31/42
post-thumbnail
{
	"strict": {
    "description": "Enable all strict type checking options.",
    "type": "boolean",
    "default": false,
    "markdownDescription": "Enable all strict type checking options.\n\nSee more: https://www.typescriptlang.org/tsconfig#strict"
  },
}

Enable all strict type checking options.

  • —noImplicitAny
  • —noImplicitThis
  • —strictNullChecks
  • —strictFunctionTypes
  • —strictPropertyInitialization
  • —strictBindCallApply
  • —alwaysStrict

—noImplicitAny

Raise error on expressions and declarations with an implied any type.

명시적이지 않게 any 타입을 사용하여 표현식과 선언에 사용하면 에러를 발생

function noImplicitAnyTestFunc(arg) {
  console.log(arg);
}

//(parameter) arg: any
//'arg' 매개 변수에는 암시적으로 'any' 형식이 포함됩니다.ts(7006)
  • TypeScript 가 추론을 실패한 경우, any 가 맞으면 any 라고 지정
  • 아무것도 쓰지 않으면, 에러를 발생
  • 이 오류를 해결하면, any 라고 지정되어 있지 않은 경우 any 가 아닌 것 (타입 추론)

suppressImplicitAnyIndexErrors

Suppress —noImplicitAny errors for indexing objects lacking index signatures.

See issue #1232 for more details.

noImplicitAny 사용할 때, 인덱스 객체에 인덱스 signature 가 없는 경우 오류가 발생하는 데 이를 예외 처리한다.

var obj = {
  bar: 10
};

obj['foo'] = 10; 
// '"foo"' 형식의 식을 '{ bar: number; }' 인덱스 형식에 사용할 수 없으므로 요소에 암시적으로 'any' 형식이 있습니다.
// '{ bar: number; }' 형식에 'foo' 속성이 없습니다.ts(7053) 

obj['bar'] = 10; // okay

obj.baz = 10;
// any
// '{ bar: number; }' 형식에 'baz' 속성이 없습니다.ts(2339)
  • obj[’foo’] 로 사용할 때, 인덱스 객체라 판단하여, 타입에 인덱스 시그니처가 없는 경우, 에러를 발생시킨다.
  • 이때 suppressImplicitAnyIndexErrors 옵션을 사용하면, 이런 경우 예외로 간주하여 에러를 발생시키지 않음

—noImplicitThis

Raise error on this expressions with an implied any type.

명시적이지 않게 any 타입을 사용하여, this 표현식에 사용하면 에러를 발생시킴

function noImplicitThisTestFunc(name: string, age: number) {
  this.name = name;
  this.age = age;

  return this;
  // any
  // 'this'에는 형식 주석이 없으므로 암시적으로 'any' 형식이 포함됩니다.ts(2683)
}

console.log(noImplicitThisTestFunc.call({ height: 160 }, 'Mark', 36));
console.log(noImplicitThisTestFunc.call({ height: 170 }, 'Mark', 36));
console.log(noImplicitThisTestFunc.call({ height: 180 }, 'Mark', 36));
function noImplicitThisTestFunc(this, name: string, age: number) {
  // (parameter) this: any
  // 'this' 매개 변수에는 암시적으로 'any' 형식이 포함됩니다.ts(7006)
  
  this.name = name;
  this.age = age;

  return this;
}
  • 첫번째 매개변수 자리에 this 를 놓고, this 에 대한 타입을 어떤 것이라도 표현하지 않으면, noImplicitAny 가 오류를 발생시킴.
  • JavaScript 에서는 매개변수에 this 를 넣으면, 이미 예약된 키워드가 SyntaxError 가 발생
  • call / apply / bind 와 같이 this 를 대체하여 함수 콜을 하는 용도로도 쓰임
  • this 를 any 로 명시적으로 지정하는 것은 합리적(구체적인 사용처가 있는 경우 타입을 표현하기도 함)
class NoImplicitThisTestClass {
  private _name: string;
  private _age: number;

  constructor(name: string, age: number) {
    this._name = name;
    this._age = age;
  }

  public print(this: NoImplicitThisTestClass) {
    console.log(this._name, this._age);
  }
}

new NoImplicitThisTestClass('Mark', 36).print();
  • Class 에서는 this 를 사용하면, noImplicitThis 와 관련한 에러가 나지 않음
  • Class 에서 constructor 를 제외한 멤버 함수의 첫번째 매개변수도 일반 함수와 마찬가지로 this 를 사용할 수 있음.

—strictNullChecks

In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any (this one exception being that undefined is also assignable to void).

  • strictNullChecks 모드에서는 null 및 undefined 값이 모든 유형의 도메인에 속하지 않으며, 그 자신을 타입으로 가지거나, any 일 경우에만 할당이 가능함
  • 한 가지 예외는 undefined 에 void 할당 가능
const a: number = null;
// 'null' 형식은 'number' 형식에 할당할 수 없습니다.ts(2322)
const b: string = undefined;
// 'undefined' 형식은 'string' 형식에 할당할 수 없습니다.ts(2322)
const c: number | null = null;
const d: any = null;
const e: any = undefined;
const f: void = undefined;
  • strictNullChecks 를 적용하지 않으면,
    • 모든 타입은 null, undefined 값을 가질 수 있음
    • string 으로 타입을 지정해도, null 혹은 undefined 값을 할당 할 수 있음
  • strictNullChecks 를 적용하면,
    • 모든 타입은 null, undefined 값을 가질 수 없고, 가지려면 union type 을 이용해서 직접 명시해야 함.
    • any 타입은 null 과 undefined 를 가진다. 예외적으로 void 타입의 경우 undefined 를 가진다.
  • strictNullChecks 를 적용하지 않고, 어떤 값이 null 과 undefined 를 가진다는 것을 암묵적으로 인정하고 계속 사용하다 보면, 정확히 어떤 타입이 오는지를 개발자 스스로 간과할 수 있음
  • 정말로 null 과 undefined 를 가질 수 있는 경우, 해당 값을 조건부로 제외하고 사용하는 것이 좋음
  • 이 옵션을 켜고 사용하는 경우,
    • 사용하려는 함수를 선언한 때부터 매개 변수와 리턴 값에 정확한 타입을 지정하려는 노력을 기울여야 하고, 기울이게 될 것임.

—strictFunctionTypes

Disable bivariant parameter checking for function types.

함수 타입에 대한 bivariant 매개변수 검사를 비활성화

Question : Which of the following types could be subtypes of Dog -> Dog ?

  1. Greyhound → Greyhound
  2. Greyhound → Animal
  3. Animal → Animal
  4. Animal → Greyhound

(Animal -> Geryhound) <: (Dog -> Dog)

  • 반환 타입은 공변적(covariant)
  • 인자 타입은 반공변적(contravatiant)
  • TypeScript 에서 인자 타입은 공변적이면서, 반공변적인게 문제!
  • 이 문제를 해결하는 옵션이 strictFunctionTypes
  • 옵션을 켜면, 에러가 안나던걸 에러가 나게 함
const button = document.querySelector('#id') as HTMLButtonElement;

button.addEventListener('keydown', (e: MouseEvent) => {});

// 이 호출과 일치하는 오버로드가 없습니다.
// 오버로드 1/2('(type: "keydown", listener: (this: HTMLButtonElement, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions | undefined): void')에서 다음 오류가 발생했습니다.
//   '(e: MouseEvent) => void' 형식의 인수는 '(this: HTMLButtonElement, ev: KeyboardEvent) => any' 형식의 매개 변수에 할당될 수 없습니다.
//     'e' 및 'ev' 매개 변수의 형식이 호환되지 않습니다.
//       'KeyboardEvent' 형식에 'MouseEvent' 형식의 button, buttons, clientX, clientY 외 12개 속성이 없습니다.
// 오버로드 2/2('(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void')에서 다음 오류가 발생했습니다.
//   '(e: MouseEvent) => void' 형식의 인수는 'EventListenerOrEventListenerObject' 형식의 매개 변수에 할당될 수 없습니다.
//     '(e: MouseEvent) => void' 형식은 'EventListener' 형식에 할당할 수 없습니다.
//       'e' 및 'evt' 매개 변수의 형식이 호환되지 않습니다.

—strictPropertyInitialization

Ensure non-undefined class properties are initialized in the cnostructor

정의되지 않은 클래스의 속성이 생성자에게 초기화되었는지 확인함.

이 옵션을 사용하려면 —strictNullChecks 를 사용하도록 설정해야 함.

class Person {
  private _name: string;
  // 속성 '_name'은(는) 이니셜라이저가 없고 생성자에 할당되어 있지 않습니다.ts(2564)
  private _age: number;
  // 속성 '_age'은(는) 이니셜라이저가 없고 생성자에 할당되어 있지 않습니다.ts(2564)

  constructor() {}

  public print() {
    console.log(this._name, this._age);
  }
}

constructor 에서 초기값을 할당한 경우 ⇒ 정상

class Person {
  private _name: string;
  private _age: number;

  constructor(name: string, age: number) {
    this._name = name;
    this._age = age;
  }

  public print() {
    console.log(this._name, this._age);
  }
}

constructor 에서 안하는 경우

  • 보통 다른 함수로 이니셜라이즈 하는 경우(async 함수)
  • constuctor 에는 async 를 사용할 수 없음
class Person {
  private _name!: string;
  private _age!: number;

  public async initialize(name: string, age: number) {
    this._name = name;
    this._age = age;
  }

  public print() {
    console.log(this._name, this._age);
  }
}

—strictBindCallApply

Enable stricter checking of the bind, call, and apply methods on functions.

bind, call, apply 에 대한 엄격한 검사 수행

  • Function 의 내장 함수인 bind, call, apply 를 사용할 때, 엄격하게 체크하도록 하는 옵션
  • bind 는 해당 함수 안에서 사용할 this 인자를 설정해주는 역할을 하고, call 과 apply 는 this 와 인자를 설정한 후, 실행까지 함.
  • call 과 apply 는 인자를 설정하는 방식에서 차이점이 있음.
    • call 은 함수의 인자를 여러 인자의 나열로 넣어서 사용하고, apply 는 모든 인자를 배열 하나로 넣어서 사용함.

—alwaysStrict

Parse in strict mode and emit “use strict” for each source file

각 소스 파일에 대해 JavaScript 의 strict mode 로 코드를 분석하고, “엄격하게 사용”을 해제함

var e1 = 015;
// ECMAScript 5 이상을 대상으로 하는 경우 8진수 리터럴을 사용할 수 없습니다. '0o15' 구문을 사용하세요.ts(1085)
var e2 = { p: 1, p: 2 };
// 개체 리터럴은 이름이 같은 여러 속성을 가질 수 없습니다.ts(1117)
var e3;
delete e3;
// strict 모드에서는 식별자에 대해 'delete'를 호출할 수 없습니다.ts(1102)
// 'delete' 연산자의 피연산자는 속성 참조여야 합니다.ts(2703)

syntax 에러가 ts error로 나옴

컴파일된 JavaScript 파일에 “use strict” 추가됨.

profile
성장하는 개발자 유슬이 입니다!

0개의 댓글