typescript 語法總結


typescript中的數據類型
1.基礎類型 string,number,null,undefined,boolean

undefined:一個沒被分配值的變量

null:人為分配一個空值

strictNullChecks: tsconfig.json中配置項,值為on時,在使用可能是null的值前,需要顯示的檢查

2.數組類型Array<T>,T代表數組中的元素類型(本寫法要求元素類型統一)

3.any,unknown,noImplictAny

unknown:是any的替代品,將unknown類型變量賦值給其它類型變量時,會報錯。

noImplictAny:(implict:隱式  inplict:顯式):項目中是否允許隱式any,tsconfig.json中配置項

 

類型標注  let len:Number = 11;  //也可寫成let len = 11,ts將進行類型推導               窄化??

函數:規定輸入輸出值類型

function greet(name:string):number{

  console.log(name)

}

匿名函數 contexture  typing:根據上下文猜測匿名函數參數的類型

const arr = ['frist','second','third'];

arr.forEach(function(s){  //匿名函數中當前項s,通過上下文推導出為string類型,所以支持toUpperCase方法

  console.log(s.toUpperCase())

})

聯合類型:ts會針對聯合類型做排除法,聯合類型只能使用兩個類型公共的方法。

function greet(name:string | number):number{

  // 只能使用傳入類型公共的方法

  if(typeof name === 'string'){  console.log(id);  return;}

  console.log(name.toUpperCase());

 }

類型別名type:支持多種類型組合(&),可以簡單理解為字符串的替換
type id=number | string;

type Point = {x:name;y:number;}

type Bear = Point & {honey:boolean}  //多種類型組合(&)

let uid :id = 100  //可以簡單理解為字符串的替換, typeof uid 會返回number而不是id

type更多用法:
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;  // 對T進行Callback操作
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
 

接口interface:支持繼承extends,接口被定義兩次時定義的屬性會合並(但相同屬性不能更改類型,高階能力)

interface Point{ x:name;y:number;  }

interface Bear extends Point{   honey:boolean }  //繼承

類型別名和接口,都可以按以下方式調用:
const bear1:Bear = {
    x:12,
    y:'lele'
}
console.log(bear1)
 
 更多知識見 《typescript中的interface和type到底有什么區別詳解》https://www.jb51.net/article/163299.htm
 

類型斷言assertion,只是提示作用

const x = 'hello' as number // 可使用 const x = ('hello' as unknown) as string  來欺騙ts

html元素對應的接口名稱  https://www.cnblogs.com/liuxu-xrl/p/15401274.html

 

字面類型:常量const的值為字面值,不能修改。相對於let 。

可以用字面類型約束一些特殊的函數:

interface options {
    id:number
}
// 字面類型
function configure(x:options | 'auto'){
    console.log(x)
}
configure('auto');
configure({id:1});
configure('');  //類型“""”的參數不能賦給類型“options | "auto"”的參數。
 
字面類型的坑點:只能處理當前一級傳值

function handleReq(url:string,method: "GET"|"POST"){
    console.log(url,method)
}
const req = { url:'http://abd.com',method:"GET" };
// handleReq(req.url, req.method);   // 報錯類型“string”的參數不能賦給類型“"GET" | "POST"”的參數。
正確寫法0:
handleReq(req.url,"GET")
正確方法1:
handleReq(req.url, req.method as "GET")
正確方法2:
const req2 = { url:'http://abd.com', method:"GET"  as "GET"};
handleReq(req.url,req.method)
正確方法3:
const req2 = { url:'http://abd.com',method:"GET"}  as const;
handleReq(req2.url,req2.method)
 
js對象逃避類型檢查方式
strictNullChecks:true時,需要顯式的檢查可能是null的值
function doSomeThing(x:string | null){
    console.log("hello,"+x.toUpperCase());      //報錯: 對象可能為 "null"。
    console.log("hello,"+x !.toUpperCase());     // 可以用!操作符,來斷言某個值不是空值
}
 
枚舉類型 enum:枚舉類型默認會返回數字,支持反向取屬性(也可以賦值為字符串,但是沒必要,因為可以反向獲取;也可以混合不同的數據類型,但是會增加復雜度)
enum Direction {
    up=1,
    down,
    left,
    right
}
console.log(Direction.down,Direction.left)  //2 3 返回數字
console.log(Direction[Direction.left])  //left   反向操作提取Enumerate中的字符串(屬性名稱),也叫Reverse Mapping
function f(obj:{up:number}){
  return obj.up
}
f(E)
f({up:1,down:2})  // Error 類型“{ up: number; down: number; }”的參數不能賦給類型“{ up: number; }”的參數。對象文字可以只指定已知屬性,並且“down”不在類型“{ up: number; }”中。
 
泛型:一種抽象一類事物的共性特征的編程手段,它允許將類型作為其它類型的參數(表現形式),從而分離不同關注點的實現(作用)。泛型可以根據傳入的函數的參數,自動推導出泛型類型和函數返回值類型。
關注點(interest Point)不同:程序里有三種表達:
接口interface:一種方面的 描述,一個類型可以擁有多個方面的特性
繼承inheritance:一種強表達。松樹->extends->樹
泛型Generics:是對共性的 提取。e.g 在造床這件事務上,桃木,紅木等等木頭都有這個作用
e.g
 
// 以下方式,只能處理number類型
function identity1(arg:number):number{
    return arg;
}

// 泛型函數
// 通過 鑽石操作符<>,傳入泛型的參數,結合函數的參數(類型)和函數的返回值類型,幫我們支持所有類型
function identity2<Type>(arg:Type):Type{
    return arg
}
let out2 = identity2<string>('MyString');   //等價於 let out = identity2('MyString');  此時,可以通過值推導出傳入值類型
// out2 = 100; //不能將類型“number”分配給類型“string”。

// 泛型類
class GenericNumber<T>{
    private zeroValue:T;
    constructor(v:T){
        this.zeroValue = v;
    }
    public add(x:T,y:T){
        return this.zeroValue + '' + x + y;  //運算符“+”不能應用於類型“T”和“T”。=> 因為僅數字能進行運算
    }
}
let gener = new GenericNumber<string>('hello,');
console.log(gener.add('Lucy','Lily'));  //hello,LucyLily

// extends interface 給泛型添加約束
interface Lengthwise{
    length:number
}
function loggingIdentity<Type extends Lengthwise>(arg: Type):Type{  // 讓Type繼承 Lengthwise以支持.length
    console.log(arg.length);  // <Type  extends Lengthwise>改成<Type>時,因不確定Type類型,所以找不到.length屬性,導致報錯
    return arg
}
loggingIdentity<string>('test')  // 也可簡寫為 loggingIdentity('test') ,通過傳入值自動推導Type

// type keyof 給泛型添加約束
type Point = {x:number;y:number}
type P = keyof Point;   //P = 'x' | 'y',即Point中所有的參數(屬性)

function getProperty<Type,Key extends keyof Type>(obj:Type,key:Key){
    console.log(obj[key])
    return obj[key]
}
let x1 = {a:1,b:2,c:3,d:4}; //因為是靜態的,所以可以用keyof操作符獲取所有的key,若對象x1的類型為any,那么keyof就沒有意義了
// x1.z= 10;  // 類型“{ a: number; b: number; c: number; d: number; }”上不存在屬性“z”。
getProperty(x1,"d")
// getProperty(x1,"m") //類型“"m"”的參數不能賦給類型“"d" | "a" | "b" | "c"”的參數。
實例化泛型類型,將類作為參數傳入
function create<Type>(c:{new ():Type}):Type{  // 也可寫為function create<Type>(c:new ()=>Type):Type{
  return new c();
}
create(Foo)  //返回Foo的實力
e.g 實戰實例
class BeeKeeper {
    hasMask : boolean = true;
}
class ZooKeeper {
    nametags: string = 'Mikle';
}
class Animal {
    numLegs : number = 4;
}
class Bee extends Animal{
    keeper:BeeKeeper = new BeeKeeper();
}
class Lion extends Animal{
    keeper:ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new()=>A):A{
    return new c();
}
console.log( createInstance(Lion).keeper.nametags );  //返回一個
console.log( createInstance(Bee).keeper.hasMask );
 
窄化(Type Narrowing)本質是重新定義類型,解決聯合類型校驗的問題
  if + typeof:
typeof返回值類型:string","number","bigint","boolean","symbol","undefined","object","function"。注意typeof null==='object'
真值窄化:幫我們更好的應對null,undefined,0等情況的判斷
JavaScript真值表(if時會進else的):0,null,undefined,NaN," "(the empty string),0n(the bigint version of zero)
相等性窄化:隱式的窄化方法,相等性窄化。===,!==,== ,and != 都可以用來窄化類型。
interface Container{
    value:number | null | undefined;
}
function mulValue(container:Container,factory:number){
    if(container.value !=null){  //此處!=可以過濾掉null,undefined兩種類型(!=兩側的 undefined和null都會轉成false )。如果替換為!==,會報錯 ,因為到時 Container.value為 numberundefined
        container.value *= factory;
        return container.value
    }
    return container.value;
}
//number類型
let data = mulValue({value:10},2);
console.log(data)
//null或undefined類型
let data2 = mulValue({value:undefined},2);
console.log(data2)
 
in操作符窄化(type定義時)
type Fish = { swim:()=>void };
type Bird = { fly:()=>void };
function move(animal:Fish | Bird){
    if('swim' in animal)    return animal.swim();
    else animal.fly()
}
class myFish{
    public swim(){
        return 'swim'
    }
}
console.log(move(new myFish()));

// instanceof 做窄化
// 此處Date必須是真實存在的Function類型,不能是type
function move1(time: Date | string){
    if( time instanceof Date){
        console.log('time',time)
        return 'time'
    }
}
move1(new Date());
 
組合類型推導
let x = Math.random() < 0.5 ? 10: "hello world!"; // 系統會自動推導出x為number或string類型
// xx = new Date() //Error 不能將類型“Date”分配給類型“string | number”。  因為ts推導出 只能賦值為number或string類型
 
 
控制流分析:
ts是如何做窄化的?在語法分析階段,ts編譯器識別出類型衛兵表達式(e.g if(typeof padding === 'number' ) 、instanceof).然后對返回值邏輯分別做窄化,窄化的本質是重新定義類型。
// 控制流窄化
function exp1(){
    let  x  :string | number | boolean;
    x = Math.random()>0.5;  // boolean
    if(Math.random()<0.5){
        x='hello';  // string
        console.log(2,typeof x);
    }
    else{
        x = 100;    // number
        console.log(3,typeof x);
    }
    return x;   //string | number,沒有Boolean了,因為上面的if,else語句已經把Boolean的可能干掉了
}
exp1();
 
 
斷言操作符:
Assertion操作符as:提示ts某種類型是什么,當用戶比ts更了解類型時使用,as影響的是當前函數內部
predicate操作符is:用戶自定義的類型守衛,用於幫助Typescript Narrowing  ,is影響的是當前函數的調用邏輯,函數內無效
function isFish(pet:Fish | Bird) : pet is Fish {
    // return pet.swim !== undefined  // Error 類型“Bird”上不存在屬性“swim”,因為pet is Fish
    return ( pet as Fish).swim !== undefined;  //內部窄化邏輯
}
let pet = {
    fly:()=>{}
}
if(isFish(pet)){
    pet.swim()   //上面有了 pet is Fish,才不報錯 Bird無swim方法
}
else pet.fly();
 

判別的聯合窄化(Discriminated unions)
interface Circle{  // 圓
    kind:'circle';
    radius:number;
}
interface Square{   //方形
    kind:'square',
    sideLength:number;
}
type Shape = Circle | Square;
// 計算面積
function getArea(shape : Shape){
    switch(shape.kind){
        case 'circle':
            return Math.PI * shape.radius ** 2; // ** 平方
        case 'square':
            return shape.sideLength ** 2;
    }
}
 
Nevel:不應該出現的類型
interface Circle{  // 圓
    kind:'circle';
    radius:number;
}
interface Square{   //方形
    kind:'square',
    sideLength:number;
}
interface Trips{
    kind:'trips';
    value:number
}
type Shape = Circle | Square | Trips;
// 計算面積
function getArea(shape : Shape){
    switch(shape.kind){
        case 'circle':
            return Math.PI * shape.radius ** 2; // ** 平方
        case 'square':
            return shape.sideLength ** 2;
        default:
            const _value:never = shape; // Error 不能將類型“Trips”分配給類型“never”。
            return _value;
    }
}
 
inter 類型推導
// e.g 提取多層數組里的值
type Flatterned<T> = T extends Array<infer V>?Flatterned<V>:T;
function flattern<T extends Array<any>>(arr:T):Array<Flatterned<T>>{
    return (new Array()).concat(...arr.map(x=>Array.isArray(x)?flattern(x):x))
}
let val = flattern([1,2,4,[5,[6,[7,[[[9]]]]]]]);
console.log(val)  // [1, 2, 4, 5,6, 7, 9]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM