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.