TypeScript: Menempatkan tsconfig di rak. Bagian 2 - Segala sesuatu tentang ketegasan

Di artikel terakhir, saya membahas berbagai fitur dari beberapa pengaturan TypeScript umum. Artikel ini akan berfokus pada apa yang disebut "bendera ketat".





Sebenarnya, TypeScript di luar kotak tidak jauh berbeda dengan JavaScript. Oleh karena itu, jika Anda tidak mengubah konfigurasi proyek pada awalnya, sebagian besar keunggulan bahasa ini tidak akan digunakan. Ada kesan menggunakan TypeScript dalam bentuk ini, tapi tidak banyak.





, : tsconfig.json



, strict



compilerOptions



true



. TypeScript . , ยซยป , . .





tsconfig.json



. : Strict Checks



Linter Checks



โ€“ . Advanced



.





Strict Checks

, . : strict



, alwaysStrict



, noImplicitAny



, strictNullChecks



, strictFunctionTypes



, strictPropertyInitialization



, noImplicitThis



, strictBindCallApply



.





false



, , โ€“ true



.





, , , , - strict



alwaysStrict



. .





alwaysStrict

: / : .





alwaysStrict



"use strict"



. , alwaysStrict



JavaScript TypeScript.





strict

: / : / .





strict



. Strict Checks



, alwaysStrict



. , .





โ€“ . strict: true



, , . , TypeScript , , JavaScript.





. . , - false



.





strict



โ€“ TypeScript. , release notes , , .





:





{
  "compilerOptions": {
    "alwaysStrict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "strictBindCallApply": true,
  }
}
      
      



, , .





noImplicitAny

: / :





, TypeScript.





any



. , , . JavaScript. TypeScript, JavaScript any



, .





any



ยซ , ยป. , . TypeScript :





//   
let a: number = 5
//  
let b = 'hello'

//        
// value     any
function someFunction (value) {
  //       
  console.log(value.subtr(3))
}
      
      



, , any



, JavaScript, TypeScript . . . , TypeScript JavaScript . noImplicitAny



, .





, any



. , (implicit) any



, - .





//         any
function someFunction (value: any) {
  console.log(value.subtr(3))
}
      
      



any



, . noImplicitAny



.





ESLint no-explicit-any



. any



warning, .





strictNullChecks

: / :





TypeScript. noImplicitAny



.





JavaScript โ€“ undefined



null



, TypeScript . , . : string



, boolean



, number



. โ€“ undefined



null



:





function someFunction (value: number) {
  //      value  undefined  null
  return value * 2
}

someFunction(5)
//    
someFunction(null)
//   
someFunction(undefined)
      
      



( ) . null



(undefined



). . , Java NullPointerException .





strictNullChecks



. undefined



null



, , . :





function someFunction (value: number) {
  // value    number
  return value * 2
}

someFunction(5)
//    
someFunction(null)
someFunction(undefined)
      
      



undefined



null



, . , , . , .





//  ยซ?ยป  undefined,  ยซ| nullยป - null
function someFunction (value?: number | null) {
  if (value == null) {
    return 0
  }
  return value * 2
}
      
      



. . (, ), , . , , null



, . . , json- .





. , , JavaScript . .





strictNullChecks



โ€“ Any



, unknown



, object



, void



, undefined



, null



and never



assignability.





strictPropertyInitialization

: / : / strictNullChecks







strictPropertyInitialization



, :





class User {
  name: string
  // email    ,   
  //  ,    
  email: string

  constructor (name: string) {
    this.name = name
  }
}
      
      



strictNullChecks



.





strictFunctionTypes

: / :





strictFunctionTypes: true



. , :





interface StringOrNumberFunc {
  (value: string | number): void
}

function someFunction (value: string) {
  console.log(value)
}

//   
// string | number   string
let func: StringOrNumberFunc = someFunction

func(10)
func('10')
      
      



noImplicitThis

: / :





this



, . :





class SomeClass {
  multiplier: number = 5

  createSomeFunction (value: number) {
    return function () {
      //   -  this     SomeClass
      return value * this.multiplier
    }
  }
}
      
      



this



, function



. , function



arrow function



.





, - this



:





function sayHello (name: string) {
  console.log(this.helloWord + ' ' + name)
}
      
      



this



. this



bind



, call



, apply



. :





//   this  ยซยป
//       
function sayHello (this: HelloStyle, name: string) {
  console.log(this.helloWord + ' ' + name)
}

//   
interface HelloStyle {
  helloWord: string
}

class HawaiiStyle implements HelloStyle {
  helloWord = 'Aloha'
}

class RussianStyle implements HelloStyle {
  helloWord = ','
}

//  
sayHello.bind(new HawaiiStyle())('World')
sayHello.call(new RussianStyle(), 'World')
sayHello.apply(new RussianStyle(), ['World'])
      
      



.





strictBindCallApply

: / :





strictBindCallApply



โ€“ : bind



, call



, apply



.





function someFunction (value: string) {
  console.log(value)
}

someFunction.call(undefined, '10')
// ,      
someFunction.call(undefined, false)
      
      



. // @ts-ignore



.





Strict Checks

  • . TypeScript





  • strict: true



    . , TypeScript.





  • alwaysStrict



    TypeScript, JavaScript. . . "use strict"



    .





  • noImplicitAny



    strictNullChecks



    strictPropertyInitialization



    . strictFunctionTypes



    noImplicitThis



    . strictBindCallApply



    .





Linter Checks

โ€“ , , . ESLint. Linter Checks



ESLint. :





{
  "compilerOptions": {
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
  }
}
      
      



false



, , โ€“ true



.





noPropertyAccessFromIndexSignature



noUncheckedIndexedAccess



. , , Strict Checks



. , strict



.





, . noPropertyAccessFromIndexSignature



noUncheckedIndexedAccess



. , Strict Checks



, strict



.





ESLint. , ESLint TSLint. TSLint Migration Guide ESLint rules for TSLint.





.





noPropertyAccessFromIndexSignature

: / : / /





noPropertyAccessFromIndexSignature



aka dot notation



, , (aka arbitrarily-named properties, index signatures).





interface User {
  //   
  login: string
  email: string

  //  
  [key: string]: string
}

const user: User = {
  login: 'hello',
  email: 'hello@example.com'
}

// c noPropertyAccessFromIndexSignature: true
//     
const username = user.name

//      
const username2 = user['name']
      
      



aka bracket notation. noImplicitAny



- .





โ€“ . , . dot notation



, , . . .





, noUncheckedIndexedAccess



.





noUncheckedIndexedAccess

: / : / / strictNullChecks



/





.





interface User {
  //   
  login: string
  email: string

  //  
  [key: string]: string
}

const user: User = {
  login: 'hello',
  email: 'hello@example.com'
}

//   username - string
const username = user['name']
      
      



, username



string.



, . : [key: string]: string | undefined



. , . , - undefined



.





noUncheckedIndexedAccess



. .





. :





const strings: string[] = ['hello']
//   number    string
const number = strings[100]
      
      



, undefined



. noUncheckedIndexedAccess



string | undefined



.





, ยซยป , undefined



โ€“ . ?





:





const strings: string[] = ['hello']
//     number     string | undefined
const number = strings[0]
      
      



:





function upperCaseAll(strings: string[]) {
  for (let i = 0; i < strings.length; i++) {
      //    
      console.log(strings[i].toUpperCase());
  }
}
      
      



, , , . .





noUncheckedIndexedAccess



, TypeScript. , .





strictNullChecks



.





noImplicitReturns

: / : / ESLint: consistent-return,





, :





function lookupHeadphonesManufacturer(color: 'blue' | 'black'): string {
  if (color === 'blue') {
    return 'beats'
  }
  //  return
}
      
      



ESLint consistent-return



, TypeScript.





noFallthroughCasesInSwitch

: ESLint / : / ESLint: no-fallthrough





break



switch/case



:





switch (value) {
  case 0:
    console.log('even')
    //  break
  case 1:
    console.log('odd')
    break
}
      
      



no-fallthrough



.





noUnusedLocals

: production ESLint / : / ESLint: no-unused-vars





:





function createKeyboard (modelID: number) {
  //   
  const defaultModelID = 23

  return {
    type: 'keyboard',
    modelID
  }
}
      
      



. ยซยป , .





development



ESLint no-unused-vars



.





noUnusedParameters

: production ESLint / : / ESLint: no-unused-vars





:





function createDefaultKeyboard (modelID: number) {
  const defaultModelID = 23

  return {
    type: 'keyboard',
    modelID: defaultModelID
  }
}
      
      



noUnusedParameters



. development



ESLint no-unused-vars



.





Linter Checks







  • ,





  • noPropertyAccessFromIndexSignature



    noUncheckedIndexedAccess



    Strict Checks



    , strict







  • : noFallthroughCasesInSwitch



    , noUnusedLocals



    , noUnusedParameters



    . noImplicitReturns







Advanced

, , . . :





{
  "compilerOptions": {
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    
    "noImplicitUseStrict": false,
    "suppressExcessPropertyErrors": false,
    "suppressImplicitAnyIndexErrors": false,
    "noStrictGenericChecks": false,
  }
}
      
      



allowUnreachableCode



allowUnusedLabels



โ€“ Linter Checks



.





true



, false



โ€“ .





. no



, . . ยซ ยป. allow



โ€“ ยซ ยป. - noUnreachableCode



noUnusedLabels



.





: noImplicitUseStrict



, noStrictGenericChecks



, suppressExcessPropertyErrors



suppressImplicitAnyIndexErrors



Base Strict Checks.



:





false



false



!





, TypeScript !





, ( noImplicitUseStrict



) , JavaScript.





99.9% .





- .





allowUnreachableCode

: production / : / ESLint: no-unreachable,





โ€“ , return, throw, break, continue:





function fn (n: number) {
  if (n > 5) {
    return true
  } else {
    return false
  }

  //  
  return true
}
      
      



development



. no-unreachable



, TypeScript.





allowUnusedLabels

: production ESLint / : / ESLint: no-unused-labels





. , , :





function verifyAge (age: number) {
  if (age > 18) {
    //    label
    verified: true
  }
}
      
      



no-unused-labels



.





noImplicitUseStrict

, / alwaysStrict







"use strict"



target



, ES6



. alwaysStrict



, target



. - .





noImplicitUseStrict



alwaysStrict



true



, , .





suppressExcessPropertyErrors

,





, , :





interface Point {
  x: number
  y: number
}

const p: Point = {
  x: 1,
  y: 3,
  //  z     Point
  z: 10
}
      
      



JavaScript, . . // @ts-ignore



.





suppressImplicitAnyIndexErrors

, / noImplicitAny







, , , . noUncheckedIndexedAccess



:





interface User {
  //   
  login: string
  email: string

  //   
  // [key: string]: string
}

const user: User = {
  login: 'hello',
  email: 'hello@example.com'
}

//    name 
const username = user['name']
      
      



, . , - . , , , TypeScript . declaration merging



.





. , Google Maps, script. Pin:





const pin = new window.google.maps.Pin(59.9386, 30.3141)
      
      



, , google. // @ts-ignore



, . โ€“ suppressImplicitAnyIndexErrors: true



( ) :





const pin = new window['google']['maps']['Pin'](59.9386, 30.3141)
      
      



. . :





//   merging.d.ts
interface Pin {
  // 
}

interface PinConstructor {
  new(lat: number, lng: number): Pin
}

interface Window {
  google: {
    maps: {
      Pin: PinConstructor
    }
  }
}

//   
const pin = new window.google.maps.Pin(59.9386, 30.3141)
      
      



, req



res



Express.





noStrictGenericChecks

,





ยซ ยป generics



:





type A = <T, U>(x: T, y: U) => [T, U]
type B = <S>(x: S, y: S) => [S, S]

function f (a: A, b: B) {
  // OK
  b = a
  //   ,   
  a = b
}
      
      



Advanced







  • . .





  • allowUnreachableCode



    allowUnusedLabels



    , Linter Checks







  • noImplicitUseStrict



    , noStrictGenericChecks



    , suppressExcessPropertyErrors



    suppressImplicitAnyIndexErrors



    , TypeScript .









  • noImplicitUseStrict



    alwaysStrict



    .





  • noStrictGenericChecks



    , suppressExcessPropertyErrors



    suppressImplicitAnyIndexErrors



    , JavaScript TypeScript.





, :





tsconfig-checks.json



:





{
  "compilerOptions": {
    // Strict Checks
    "alwaysStrict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "strictBindCallApply": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    // Linter Checks
    "noImplicitReturns": true, // https://eslint.org/docs/rules/consistent-return ?
    "noFallthroughCasesInSwitch": true, // https://eslint.org/docs/rules/no-fallthrough
    "noUnusedLocals": true, // https://eslint.org/docs/rules/no-unused-vars
    "noUnusedParameters": true, // https://eslint.org/docs/rules/no-unused-vars#args
    "allowUnreachableCode": false, // https://eslint.org/docs/rules/no-unreachable ?
    "allowUnusedLabels": false, // https://eslint.org/docs/rules/no-unused-labels
    // Base Strict Checks
    "noImplicitUseStrict": false,
    "suppressExcessPropertyErrors": false,
    "suppressImplicitAnyIndexErrors": false,
    "noStrictGenericChecks": false,
  }
}
      
      



tsconfig-checks.json



? , , , . .





tsconfig.json



:





{
  //  
  "extends": "./tsconfig-checks.json",
  "compilerOptions": {
    //   
  }
}
      
      



Dan untuk kenyamanan pengembangan, agar kode yang tidak dapat dicapai dan variabel yang tidak digunakan tidak merusak kompilasi untuk kita, kita dapat melakukan hal berikut.





File tsconfig-dev.json



:





{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    //   ,    
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "allowUnreachableCode": true,
    "allowUnusedLabels": true
  }
}
      
      



Itu saja. Di masa mendatang, saya berencana untuk mencari tahu opsi pengoptimalan dan kinerja dan akan berbagi dengan Anda. Sampai Lain waktu!





Artikel ini berdasarkan utas saya di akun kolektif @jsunderhood .





PS: Di akun @barinbritva saya, saya terkadang juga menulis tentang TypeScript dan pengembangan.








All Articles