一.簡(jiǎn)介
TypeScript是JavaScript的超集,增加了數(shù)據(jù)類型, 幫助JS檢查錯(cuò)誤, 防止在大型項(xiàng)目中JS出現(xiàn)解釋錯(cuò)誤.
TypeScript最后還是會(huì)編譯成JS.
二. 類型
2.1 基本類型
let message: string = 'hello world 1';
let b: boolean = true;
let str: string | null | undefined = "|為聯(lián)合語(yǔ)法"
//數(shù)組
let arr1: Array<number> = [10, 20 ,30]
let arr2: number[] = [2, 3, 4]
let arr3: Array<number | string> = [666, "真的666"]
//參數(shù)展開運(yùn)算符
let arr5: number[] = [1, 2, 3]
let arr6: number[] = [4, 5]
arr5.push(...arr6)
console.log(arr5)//[LOG]: [1, 2, 3, 4, 5]
//元組
let tuple: [number, string] = [666, "這是元組"]
console.log(message, b, str, arr1, arr2, arr3, tuple);
//函數(shù)
let add = (x: number, y: number):number => x + y
console.log("合為"+add(1, 2))
//對(duì)象
let obj0: Object;
let obj: {x: number, y: number} = {x: 1, y: 2}
console.log("obj的值為" + obj.y)
//symbol 全局唯一引用
//symbol 類型表示一個(gè)獨(dú)一無(wú)二的標(biāo)識(shí)符。每個(gè)通過(guò) Symbol 函數(shù)創(chuàng)建的 symbol 都是唯一的瘦赫,即使它們的描述相同铺浇。
let s1: symbol = Symbol()
let s2 = Symbol()
// 創(chuàng)建一個(gè)唯一的 symbol
const mySymbol: symbol = Symbol("mySymbol");
// 創(chuàng)建另一個(gè)唯一的 symbol
const anotherSymbol: symbol = Symbol("mySymbol");
// 由于每個(gè) symbol 都是唯一的朵你,這兩個(gè) symbol 不相等
console.log(mySymbol === anotherSymbol); // 輸出: false
//undefined
let un: undefined = undefined;
let nu: null = null;
//message = null; //報(bào)錯(cuò),因?yàn)閱?dòng)了strictNullChecks(嚴(yán)格null校驗(yàn))
//void
let noReturn = () => {}//let noReturn: () => void
//any, 變量的默認(rèn)類型為any
let aaany //let aaany: any
//nerver
let error = () => {//let error: () => never
throw new Error("error")
}
let endless = () => {//let endless: () => never
while(true) {
}
}
2.2 自定義類型
//let 可變參數(shù)
let aString = "hello"
aString = "world"
//const 不可變參數(shù)
const bString = "666"
bString = "777"http://報(bào)錯(cuò)
//使用let來(lái)實(shí)現(xiàn)const, 將cString的類型定義為一個(gè)'can not changed string'這樣一個(gè)特殊類型
//等號(hào)前后要保持一致,否則會(huì)報(bào)錯(cuò)
let cString: 'can not changed string' = "can not changed string"
cString = "yes"http://報(bào)錯(cuò)
//使用特殊類型
function printText(text: string, aligment: "left" | "right" | "center") {
console.log(text + "---" + aligment)
}
printText("label", "center")//[LOG]: "label---center"
三. 枚舉
//數(shù)字枚舉
enum Season {
Spring,
Summer,
Fall,
Winter
}
console.log(Season.Spring)//0
console.log(Season.Fall)//2
//枚舉的原理
//轉(zhuǎn)化為JS
/*
"use strict";
var Season;
(function (Season) {
Season[Season["Spring"] = 0] = "Spring";
Season[Season["Summer"] = 1] = "Summer";
Season[Season["Fall"] = 2] = "Fall";
Season[Season["Winter"] = 3] = "Winter";
})(Season || (Season = {}));
console.log(Season.Spring); //0
console.log(Season.Fall); //2
*/
//字符串枚舉
enum Message {
Successs = "成功",
Fail = "失敗"
}
/*
var Message;
(function (Message) {
Message["Successs"] = "\u6210\u529F";
Message["Fail"] = "\u5931\u8D25";
})(Message || (Message = {}));
*/
//異構(gòu)枚舉
enum Anser{
N,
Y = "YES"
}
/*
var Anser;
(function (Anser) {
Anser[Anser["N"] = 0] = "N";
Anser["Y"] = "YES";
})(Anser || (Anser = {}));
*/
//枚舉成員
enum Char {
//const類型俐填, 編譯時(shí)確定值
a, //未定義
b = Char.a, //對(duì)其他枚舉的引用
c = 1 + 3, //常量
//computed類型伶氢, 運(yùn)行時(shí)計(jì)算確定值
d = Math.random(),
e = "123".length
}
/*
var Char;
(function (Char) {
//const類型澈蟆, 編譯時(shí)確定值
Char[Char["a"] = 0] = "a";
Char[Char["b"] = 0] = "b";
Char[Char["c"] = 4] = "c";
//computed類型墨辛, 運(yùn)行時(shí)計(jì)算確定值
Char[Char["d"] = Math.random()] = "d";
Char[Char["e"] = "123".length] = "e";
})(Char || (Char = {}));
*/
//常量枚舉, 使用const聲明; 不會(huì)被編譯進(jìn)代碼趴俘, 相當(dāng)于預(yù)編譯的宏替換
const enum Month {
Jan,
Fri,
Mar
}
//枚舉類型
enum E {a, b}
enum F {a = 1, b = 2}
enum G {a = "hhh", b = "666"}
//let le: E = 3 //Type '3' is not assignable to type 'E'.
//let lf: F = 3 //Type '3' is not assignable to type 'F'.
let lg: G.a = G.a
四.類型接口
4.1 對(duì)象類型接口
interface list {
readonly id: number, //readonly, 只讀屬性
name: string,
age?: number //?可選參數(shù)
}
interface list1 {
readonly id: number, //readonly, 只讀屬性
name: string,
age?: number //?可選參數(shù)
}
//interface也可以繼承
interface list2 extends list, list1{
}
interface StringArray {
[index: number]:string
}
let chars: StringArray = ["A", "B", "C"]
console.log(chars[2])//C
interface Names {
[x: string]:string | undefined,
[index: number]:string
}
let names: Names = {
0: "A",
1: "B",
"2": "C",
"Wow": "真的6啊"
}
console.log(names[1], names["Wow"])//"B", "真的6啊"
4.2 函數(shù)類型接口
//普通函數(shù)變量, 不能被繼承
let add0: (x: number, y: number) => number; //add0是一個(gè)函數(shù)類型的變量
add0 = function(x, y) { //給變量復(fù)制真正的函數(shù)體
return x + y
}
console.log(add0(1, 2))// 3
//函數(shù)類型接口
interface Add1 {
(x: number, y: number): number
}
let add1: Add1 = function (x, y){
return x + y
}
console.log(add1(1, 5))//6
// 搞個(gè)別名
type Add2 = (x: number, y: number) => number
let add2: Add2 = (x, y) => x + y
console.log(add2(1, 9))//10
//可選參數(shù), z可以不傳睹簇, 且必須位于必選參數(shù)之后
function add5(x: number, y: number, defaultValue=6, z?: number) {
return z ? x + y + defaultValue + z : x + y + defaultValue;
}
console.log(add5(1, 2), add5(1, 2, 3))//[LOG]: 9, 6
五.類
//抽象類, 不能被實(shí)例化寥闪, 只能被繼承
abstract class Animal {
eat() {
console.log("eat")
}
}
class Dog extends Animal{
name: string
static food: string = "骨頭"http://類成員,使用類名調(diào)用
constructor(name: string) {
super()
this.name = name
}
run() {
}
}
console.log(Dog.prototype)
let d = new Dog("汪汪汪")
d.eat();
console.log(d, d.name)
/*
[LOG]: Dog: {
"name": "汪汪汪"
}, "汪汪汪"
*/
//哈士奇繼承自Dog
class Husky extends Dog {
color: string
constructor(name: string, color: string) {
super(name)
this.color = color
}
}
//哈士奇繼承自Dog-> 給參數(shù)增加public屬性太惠,可以不用在類里面定義color: string了
class Husky1 extends Dog {
constructor(name: string, public color: string) {
super(name)
this.color = color
}
}
//private 也可以使用#變量來(lái)實(shí)現(xiàn)private
//protect
// public
六.類型斷言
- 使用
as
或者<>
來(lái)類型斷言 - 類型斷言會(huì)在運(yùn)行時(shí)被刪除
const m1 = document.getElementById("main") as HTMLCanvasElement
const m2 = <HTMLCanvasElement>document.getElementById("main")
七.類型縮小
7.1 使用typeof
來(lái)實(shí)現(xiàn)類型守衛(wèi)
let s: string | number = "astring"
// s = 666
if (typeof s === "string") {
console.log("字符串")
} else if (typeof s === "number") {
console.log("數(shù)字")
}
let ret: typeof s
ret = "0.0"
7.2 真值縮小
function havePeople(count: number | string | null | undefined) {
if (count) {
console.log("有人")
} else {
console.log("沒(méi)人")
}
}
//針對(duì)number 非0即為true
havePeople(-1) //[LOG]: "有人"
havePeople(0) //[LOG]: "沒(méi)人"
havePeople(1) //[LOG]: "有人"
//針對(duì)string 非空字符串為true
havePeople("") //[LOG]: "沒(méi)人"
havePeople("h") //[LOG]: "有人"
//null和undefined都為false
havePeople(null) //[LOG]: "沒(méi)人"
havePeople(undefined) //[LOG]: "沒(méi)人"
//或者使用一下方法 大寫B(tài)oolean或者!!, !!其實(shí)就是取反再取反
console.log(Boolean("")) //false
console.log(Boolean("h")) //true
console.log(!!0) //false
console.log(!!1) //true
7.3 等值縮小
使用== === != !===
來(lái)實(shí)現(xiàn)
在 TypeScript 中,== 和 === 是用于比較值的操作符疲憋,它們的行為與 JavaScript 中的相同凿渊。
- == 是松散相等性比較,也稱為“不嚴(yán)格相等”缚柳。在比較時(shí)埃脏,會(huì)進(jìn)行類型轉(zhuǎn)換,嘗試使兩側(cè)的值類型相同秋忙,然后再進(jìn)行比較彩掐。
- === 是嚴(yán)格相等性比較,也稱為“嚴(yán)格相等”灰追。它不進(jìn)行類型轉(zhuǎn)換堵幽,只有在類型和值都相同時(shí)才被認(rèn)為相等。
let a: number = 5
let b: string = "5"
// 使用 ==
console.log(a == b); // 輸出: true弹澎,因?yàn)樵诒容^時(shí)會(huì)進(jìn)行類型轉(zhuǎn)換
// 使用 ===
console.log(a === b); // 輸出: false谐檀,因?yàn)閲?yán)格相等要求類型和值都相同
let n1 = 5
let n2 = 6
console.log(n1 == n2)//false
console.log(n1 === n2)//false
7.4 in
在 TypeScript 中,in 關(guān)鍵字主要用于檢查對(duì)象是否包含某個(gè)屬性裁奇。它可以用于兩個(gè)場(chǎng)景:
- 檢查對(duì)象是否包含某個(gè)屬性
let myObject = { key1: 'value1', key2: 'value2' };
if ('key1' in myObject) {
console.log('myObject has key1 property');
} else {
console.log('myObject does not have key1 property');
}
- 遍歷對(duì)象的屬性
let myObject = { key1: 'value1', key2: 'value2' };
for (let key in myObject) {
console.log(`Property: ${key}, Value: ${myObject[key]}`);
}
//[LOG]: "Property: key1, Value: value1"
//[LOG]: "Property: key2, Value: value2"
八. 函數(shù)
8.1 調(diào)用簽名
可以給函數(shù)綁定一個(gè)屬性
type DescriptionFuntion = {
description: string
(arg: number): boolean
}
function doSomething(fn: DescriptionFuntion) {
console.log(fn.description + " return" + fn(6))
}
function fn(n: number) {
console.log(n)
return true
}
fn.description = "調(diào)用簽名"
doSomething(fn)
//[LOG]: 6
//[LOG]: "調(diào)用簽名return true"
8.2 構(gòu)造簽名
- 快速生成類
- 一般需要結(jié)合泛型更好使
參考:https://blog.csdn.net/yangxinxiang84/article/details/119490185
class Cls {
name: string
constructor(name: string) {
this.name = name
}
}
//方法1 字面量方式構(gòu)造簽名
function fn0(cls: new(name: string) => Cls): Cls {
return new cls("aaa")
}
const cls0: Cls = fn0(Cls)
console.log(cls0)
function fnt<T>(cls: new(name: string) => T): T {
return new cls("ttt")
}
const clst: Cls = fnt(Cls)
console.log(clst)
//方法2 接口對(duì)象字面量方式構(gòu)造簽名
function fn1(cls: {new (name: string): Cls}, name: string): Cls {
return new cls(name)
}
const cls1: Cls = fn1(Cls, "bbb")
console.log(cls1)
//方法3 使用type或者interface
type ClsConstrutor = {
new (name: string):Cls
}
function fn2(cls: ClsConstrutor): Cls {
return new cls("ccc")
}
九.泛型
9.1 類型限制
//泛型T必須要有一個(gè)length屬性
function longest<T extends {length: number}> (a: T, b: T) {
return a.length > b.length ? a : b
}
9.2 指定類型參數(shù)
function combine<T>(arr1: T[], arr2: T[]): T[] {
return arr1.concat(arr2)
}
combine([1, 2, 3], [4, 5, 6])
// 報(bào)錯(cuò)了, 因?yàn)轭愋屯茢酁閚umber[]
// combine([1, 2, 3], ["a", "b", "c"])
// 如果你非得亂搞,那需要這樣做, 聲明數(shù)組的類型
let arr = combine<number | string> ([1, 2, 3], ["a", "b", "c"])
console.log(arr)//[LOG]: [1, 2, 3, "a", "b", "c"]
9.3 泛型約束
interface haveLength {
length: number
}
// 傳入的參數(shù)需要有l(wèi)ength屬性
function use<T extends haveLength>(args: T) {
console.log(args.length)
}
use("123")//[LOG]: 3
9.4 泛型約束中使用類型參數(shù)
function getProperties<Type, Key extends keyof Type>(t: Type, k: Key) {
return t[k]
}
let obj = {
a: 1,
b: 2
}
let ret1 = getProperties(obj, "a")
console.log(ret1)//[LOG]: 1
//let ret2 = getProperties(obj, "c")//報(bào)錯(cuò), 沒(méi)有這個(gè)key
十. This關(guān)鍵字
this的指向問(wèn)題
在 TypeScript 中桐猬,你可以在函數(shù)參數(shù)中使用 this 參數(shù),這允許你顯式地指定函數(shù)的調(diào)用方刽肠。通常溃肪,在函數(shù)內(nèi)部,this 關(guān)鍵字用于引用當(dāng)前對(duì)象音五,但對(duì)于一些情況惫撰,尤其是在回調(diào)函數(shù)或異步代碼中,JavaScript 的默認(rèn)行為可能導(dǎo)致 this 的值不是你期望的對(duì)象躺涝。this和箭頭函數(shù), 注意:this在冒號(hào)前面.如果this在冒號(hào)后面,this就是指向調(diào)用方
class MyClass {
name = "MyClass"
getName() {
return this.name
}
getConstName = () => {
return this.name
}
getThisName(this: MyClass) {
return this.name
}
}
//沒(méi)問(wèn)題
let cls = new MyClass()
console.log(cls.getName())//[LOG]: "MyClass"
//換個(gè)方式就有問(wèn)題了
//getName獲取到的是cls1的, 而不是MyClass的
let cls1 = {
name: "cls1Name",
getName: cls.getName//這是一個(gè)方法
}
console.log(cls1.getName())//[LOG]: "cls1Name"
//怎么強(qiáng)行輸出MyClass呢.
//1.使用=>, 把方法改成函數(shù)
let cls2 = {
name: "cls2Name",
getName: cls.getConstName//這是一個(gè)方法
}
console.log(cls2.getName())//[LOG]: "MyClass"
//2.使用this關(guān)鍵字
let cls3 = {
name: "cls3Name",
getName: cls.getThisName
}
console.log(cls3.getName())//報(bào)錯(cuò), 直接不讓cls3使用自己的name,只能使用MyClss的name
F
- type和interface的區(qū)別
基本相同, 但是interface更容易擴(kuò)展
//type后面跟個(gè)=
type Cls0 = {
a: number
}
let a0: Cls0 = {a: 10}
//使用&符號(hào)type增加擴(kuò)展
type Cls1 = Cls0 & {
b: number
}
let a1: Cls1 = {a: 10, b: 20}
console.log(a1)
//interface后面沒(méi)有=
interface Bill{
a: number
}
let b0: Bill = {a: 10}
// 使用extend增加擴(kuò)展
interface Bill1 extends Bill {
b: number
}
let b1: Bill1 = {a: 10, b: 20}
console.log(b1)
//使用extend給type增加擴(kuò)展 0.0
interface Cls2 extends Cls0 {
c: number
}
let c: Cls2 = {a: 10, c: 30}
console.log(c)
//interface可以多地方聲明. type多地方聲明則會(huì)報(bào)錯(cuò)
interface Win {
a: string
}
interface Win {
b: number
}
const w: Win = {
a: "this is a stirng",
b: 666
}
console.log(w)