Im letzten Artikel habe ich die verschiedenen Funktionen einiger gängiger TypeScript-Einstellungen behandelt. Dieser Artikel konzentriert sich auf die sogenannten "strengen Flaggen".
Tatsächlich unterscheidet sich TypeScript nicht wesentlich von JavaScript. Wenn Sie die Projektkonfiguration zunächst nicht optimieren, werden die meisten Vorteile der Sprache daher nicht genutzt. Es gibt ein Gefühl, TypeScript in dieser Form zu verwenden, aber nicht viel.
, : 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": {
//
}
}
Und um die Entwicklung zu vereinfachen, damit unerreichbarer Code und nicht verwendete Variablen die Kompilierung für uns nicht beeinträchtigen, können wir Folgendes tun.
Datei tsconfig-dev.json
:
{
"extends": "./tsconfig.json",
"compilerOptions": {
// ,
"noUnusedLocals": false,
"noUnusedParameters": false,
"allowUnreachableCode": true,
"allowUnusedLabels": true
}
}
Das ist alles. In Zukunft plane ich, die Optimierungs- und Leistungsoptionen herauszufinden und diese mit Ihnen zu teilen. Bis zum nächsten Mal!
Der Artikel basiert auf meinem Thread im Sammelkonto @jsunderhood .
PS: In meinem @ barinbritva- Konto schreibe ich manchmal auch über TypeScript und Entwicklung.