Typescript類型系統(tǒng)FLOW靜態(tài)檢查基本規(guī)范
Typescript是一門基于JavaScript之上的語言,重點解決了JavaScript自由類型系統(tǒng)的問題。
使用Typescript可以大大提高代碼的可靠程度。
類型系統(tǒng)
強類型和弱類型(類型安全)
強類型:語言層面限制函數(shù)的實參類型必須與形參類型相同

弱類型:語言層面不會限制實參的類型

由于這種強弱類型之分根本不是某一個權威機構的定義,所以導致后人對這種鑒定方式的細節(jié),出現(xiàn)了不一致的理解。但整體上大家的鑒定方式都是在描述強類型有更強的類型約束,而弱類型中幾乎沒有什么約束。
強類型語言中不允許有任意的隱式類型轉(zhuǎn)換,而弱類型語言中則允許任意的數(shù)據(jù)隱式類型轉(zhuǎn)換。
強類型不允許隨意的隱式類型轉(zhuǎn)換,而弱類型則是允許的。
變量類型允許隨時改變的特點,不是強弱類型的差異。
靜態(tài)類型與動態(tài)類型(類型檢查)
- 靜態(tài)類型:一個變量聲明時它的類型就是明確的,而且聲明過后,它的類型就不允許再修改。
- 動態(tài)類型:運行階段才能夠明確變量類型。動態(tài)類型語言中的變量沒有類型,變量中存放的值是有類型的。
JavaScript就是動態(tài)型語言,而且變量的類型隨時可以改變。
常用編程語言:

JavaScript自由類型系統(tǒng)的問題
JavaScript是弱類型且動態(tài)類型,甚至可以說它沒有類型。它的特征就是[任性]、[不靠譜],缺失了類型系統(tǒng)的可靠性。
JavaScript沒有編譯環(huán)節(jié)
大規(guī)模應用下,弱類型/動態(tài)類型這種優(yōu)勢就變成了短板。
弱類型的問題:君子約定有隱患,強制要求有保障。
強類型的優(yōu)勢:
- 錯誤更早暴露
- 代碼更智能,編碼更準確
- 重構更牢靠
- 減少不必要的類型判斷
Flow靜態(tài)類型檢查方案
- Flow是JavaScript的靜態(tài)類型檢查器。
- 彌補了JavaScript的不足,為JavaScript提供了更完善的類型系統(tǒng)。
- 工作原理就是通過在代碼當中添加一些類型注解方式來去標記代碼中變量或參數(shù)應該是什么類型的。
//@flow
function sum(a: number, b: number) {
return a + b
}
console.log(sum(10, 20));
console.log(sum('10', '20'));
Flow只是一個小工具。
安裝:flow-bin
通過編譯除注解
- 1.安裝flow-remove-types依賴
- 2.使用JavaScript編譯工具babel配合flw插件
flow開發(fā)者工具:flow language support
類型注解
function add(a:number,b:number){
return a+b
}
let num:number = 90
function foo():void{}
flow原始類型
const a: string = 'foobar' const b: number = Infinity // NaN // 100 const c: boolean = false // true const d: null = null const e: void = undefined const f: symbol = Symbol()
flow數(shù)組類型
const arr1: Array<number> = [1, 2, 3] const arr2: number[] = [1, 2, 3] // 元組 const foo: [string, number] = ['foo', 100]
flow對象類型
const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 }
const obj2: { foo?: string, bar: number } = { bar: 100 }
const obj3: { [string]: string } = {}
obj3.key1 = 'value1'
obj3.key2 = 'value2'
flow函數(shù)類型
//@flow
function foo (callback: (string, number) => void) {
callback('string', 100)
}
foo(function (str, n) {
// str => string
// n => number
})
flow特殊類型
// 字面量類型 const a: 'foo' = 'foo' const type: 'success' | 'warning' | 'danger' = 'success' // ------------------------ // 聲明類型 type StringOrNumber = string | number const b: StringOrNumber = 'string' // 100 // ------------------------ // Maybe 類型 const gender: ?number = undefined
任意類型 Mixedany
//@flow
// string | number | boolean | ....
function passMixed (value: mixed) {
if (typeof value === 'string') {
value.substr(1)
}
if (typeof value === 'number') {
value * value
}
}
passMixed('string')
passMixed(100)
// ---------------------------------
function passAny (value: any) {
value.substr(1)
value * value
}
passAny('string')
passAny(100)
Typescript語言規(guī)范與基本應用
任何一種JavaScript運行環(huán)境都支持。功能更為強大,生態(tài)也更健全、更完善。
Typescript是JavaScript的超集。

微軟自研的開發(fā)工具對Typescript支持特別好。
Typescript(漸進式)–前端領域中的第二語言。
Typescript缺點:
- 語言本身多了很多概念
- 項目初期,Typescript會增加一些成本
使用Typescript之前要先安裝依賴。
標準庫就是內(nèi)置對象所對應的聲明。
顯示中文錯誤信息:yarn tsc --locale zh-CN,vs-code也可以設置locale為中文
Typescript作用域
我們可以用立即執(zhí)行函數(shù)/export導出模塊來創(chuàng)建一個單獨作用域。
//立即執(zhí)行函數(shù)
(function () {
const a = 9
})()
//模塊導出
export aa = {
a: 23
}
Typescript原始類型
//原始數(shù)據(jù)類型 const a: string = 'foo' const b: number = 100 //NaN/Infinity const c: boolean = true //false const d: boolean = null const e: void = undefined const f: null = null const g: undefined = undefined const h: symbol = Symbol()
Typescript Object類型
并不單指普通的對象類型,而是泛指所有的非原始類型:對象、數(shù)組、函數(shù)。
//Object類型
const aa: object = function () { } //[]//{}
const obj: { foo: number, bar: string } = { foo: 123, bar: 'aaa' }
更專業(yè)的方式是使用接口。
Typescript數(shù)組類型
有兩種定義方式:
- 使用Array泛型
- 使用元素類型+[]
//數(shù)組類型 const arr: Array<number> = [1, 2, 3] const arr1: number[] = [1, 2, 3]
Typescript元組類型(turple)
是一種特殊的數(shù)據(jù)結構,其實元組就是一個明確元素數(shù)量以及每個元素類型的數(shù)組,各個元素的類型不必要完全相同。定義方式:字面量方式
//元組類型
//元組(tuple)
export { } //確保跟其他示例沒有成員沖突
const tuple: [number, string] = [10, 'rock']
console.log(tuple[0]); //10
console.log(tuple[1]); //rock
//解構賦值
const [num, age] = tuple
Object.entries({
foo: 123,
zar: 432
})
Typescript枚舉類型(enum)
enum Status {
Draft = 'aaa',
Unpulished = 'bbb',
Published = 'ccc'
}
如果確認代碼中不會使用索引器去訪問枚舉,就可以使用常量枚舉。
//常量枚舉
const post = {
title: 'Hello',
content: 'TypeScript',
status: 'ok'
}
枚舉類型會入侵到我們運行時的代碼,它會影響到我們編譯后的結果。我們在TypeScript中使用的大多數(shù)類型,它在經(jīng)過編譯轉(zhuǎn)換后,最終都會被移除掉,因為它只是為了我們在編譯過程中做類型檢查,但枚舉類型不會,它最終會變?yōu)橐粋€雙向鍵值對對象。
TypeScript函數(shù)類型
JavaScript中又兩種函數(shù)定義方式:
函數(shù)聲明
//函數(shù)聲明方式
// function func1(a: number, b?: number): string {
// function func1(a: number, b: number=90): string {
function func1(a: number, ...rest: number[]): string {
return 'hello'
}
func1(12, 34)
func1(30)
使用參數(shù)可選、參數(shù)默認值、剩余參數(shù)都需要放在參數(shù)列表的最后一個參數(shù)位置。
函數(shù)表達式
//函數(shù)表達式
const func2 = (a: number, b: number) => string = function (a: number, b: number): string {
return 'func2'
}
TypeScript任意類型
因為any是弱類型,也是動態(tài)類型,所以TypeScript不會對any做類型檢查。所以它存在類型安全問題,我們不要輕易去使用它。
function stringify(value: any) {
return JSON.stringify(value)
}
stringify('string')
stringify(123)
stringify(true)
let foo: any = 'string'
foo = 100
foo.bar()
隱式類型判斷
如果我們沒有通過類型注解去標注一個變量,TypeScript會根據(jù)這個變量的使用情況去推斷這個變量的類型。
//隱式類型推斷 let age = 10 //number // age = 'aaa' let foo; foo = 45 foo = 'aaa'
雖然定義變量時如果不給它指定類型,也不給初始值,TypeScript會自動幫他注解為any類型,但還是建議定義時就注明類型。
TypeScript類型斷言
在某些特殊情況下,TypeScript無法去推斷一個變量的類型,而我們作為開發(fā)者,我們根據(jù)代碼的使用情況,我們是會明確知道這個變量到底是什么類型的。類型斷言的方式:
- 使用as關鍵字
- 在變量前面使用<>(JSX中不能使用)
const nums = [12, 34, 56] const res = nums.find(i => i > 10) //斷言方式一--as關鍵字 const num1 = res as number //斷言方式二---泛型 const num2 = <number>res
類型斷言并不是類型轉(zhuǎn)換,類型轉(zhuǎn)換是代碼在運行時的概念,而類型斷言是代碼在編譯時的概念。當代碼編譯過后,斷言也就不存在了。
TypeScript接口(Interface)
一種規(guī)范或者一種契約。它可以用來去約定對象的結構。去使用一個接口,就必須去遵守它所有的約定。
interface Post {
title: string
content: string
}
function printPost(post: Post) {
console.log(post.title);
console.log(post.content);
}
printPost({
title: 'hello',
content: 'welcome'
})
//hello
//welcome
TypeScript中的接口只是為了我們有結構的數(shù)據(jù),去做類型約束的,在實際運行階段,它并沒有任何意義。
- 可選成員
- 只讀成員
- 動態(tài)成員
interface Post {
title: string
subtitle?: string //可選成員
content: string
readonly summary: string //只讀成員
}
TypeScript類(class)
類的特征:描述一類具體事物的抽象特征。
類可以用來描述一類具體對象的抽象成員。
ES6以前,JavaScript都是通過函數(shù)+原型模擬實現(xiàn)類。ES6開始,JavaScript中有了專門的class。
TypeScript增強了class的相關語法。
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
sayHi(msg: string): void {
console.log((`I am ${this.name}, ${msg}`));
}
}
類的訪問修飾符(默認是public修飾符)
class Person {
public name: string // = 'init name'
private age: number
protected gender: boolean
constructor (name: string, age: number) {
this.name = name
this.age = age
this.gender = true
}
sayHi (msg: string): void {
console.log(`I am ${this.name}, ${msg}`)
console.log(this.age)
}
}
class Student extends Person {
private constructor (name: string, age: number) {
super(name, age)
console.log(this.gender)
}
static create (name: string, age: number) {
return new Student(name, age)
}
}
const tom = new Person('tom', 18)
console.log(tom.name)
// console.log(tom.age)
// console.log(tom.gender)
const jack = Student.create('jack', 18)類的只讀屬性readonly
protected readonly gender:boolean
類與接口
接口就是把共同的特征封裝起來。
interface EatAndRun {
eat(food: string): void
run(distance: number): void
}
class Person implements EatAndRun {
eat(food: string): void {
console.log(`美美的吃:${food}`);
}
run(distance: number) {
console.log(`直立行走:${distance}`);
}
}
class Animal implements EatAndRun {
eat(food: string): void {
console.log(`美美的吃:${food}`);
}
run(distance: number) {
console.log(`直立行走:${distance}`);
}
}
一個接口只約束一個能力,一個類型去實現(xiàn)多個接口。
interface Eat {
eat(food: string): void
}
interface Run {
run(distance: number): void
}
class Person implements Eat, Run {
eat(food: string): void {
console.log(`美美的吃:${food}`);
}
run(distance: number) {
console.log(`直立行走:${distance}`);
}
}
class Animal implements Eat, Run {
eat(food: string): void {
console.log(`美美的吃:${food}`);
}
run(distance: number) {
console.log(`直立行走:${distance}`);
}
}
TypeScript抽象類
抽象類與接口有點類似,也可以用來去約束子類中必須擁有某個成員。
但是抽象類可以包含一些具體的實現(xiàn),但是接口只是成員的抽象,不包含具體的實現(xiàn)。
抽象類不能用new去實例了,只能去繼承。
abstract class Animal {
eat(food: string): void {
console.log(`咕嚕咕嚕吃:${food}`);
}
abstract run(distance: number): void
}
class Dog extends Animal {
run(distance: number): void {
console.log(`四肢爬行:${distance}`);
}
}
const d = new Dog()
d.eat('肉')
d.run(200)
TypeScript泛型
泛型:我們在定義函數(shù)、接口或類時,沒有指定具體的類型,等到使用時再去指定具體類型的特征。
function CreateNumberArray(length: number, value: number): number[] {
const arr = Array<number>(length).fill(value)
return arr
}
function CreateStringArray(length: number, value: string): string[] {
const arr = Array<string>(length).fill(value)
return arr
}
function CreateArray<T>(length: number, value: T): T[] {
const arr = Array<T>(length).fill(value)
return arr
}
const res = CreateArray<string>(3, 'foo')
TypeScript類型聲明
一個成員在定義時沒有聲明類型,在使用時單獨為它做出明確聲明。
import { camelCase } from 'lodash'
import qs from 'query-string'
qs.parse('?key=value&key2=value2')
declare function camelCase(input: string): string
const res = camelCase('hello')
以上就是Typescript類型系統(tǒng)FLOW靜態(tài)檢查基本規(guī)范的詳細內(nèi)容,更多關于Typescript類型FLOW靜態(tài)檢查的資料請關注腳本之家其它相關文章!
相關文章
JS面試中你不知道的call apply bind方法及使用場景詳解
這篇文章主要為大家介紹了JS面試中你不知道的call apply bind方法及使用場景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
Openlayer?add?mark及添加hover效果實例詳解
這篇文章主要為大家介紹了Openlayer?add?mark及添加hover效果實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11

