TypeScript基础语法


TypeScript为JavaScript的超集,是一门强类型语言

基础类型及声明方式

布尔值
let isDone: boolean = false;

数字
let decLiteral: number = 6;

字符串
let name: string = "bob";

数组
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
const ro: ReadonlyArray<number> = list;//数组只读
//ro[0] = 3; //error

元组Tuple
let x: [string, number];
x = ['hello', 10]; // OK

枚举
enum Color {Red = 1, Green = 2, Blue = 4}//默认是从0开始为元素变号,可以手动赋值
let c: Color = Color.Green;

Any不确定类型
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;

void:声明函数没有返回值
function warnUser(): void {
    console.log("This is my warning message");
}

Null 和 Undefined,没啥实际意义
let u: undefined = undefined;
let n: null = null;

Never,表示的是那些永不存在的值的类型。 
例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 
变量也可能是 never类型,当它们被永不为真的类型保护所约束时。
function error(message: string): never {
    throw new Error(message);
}

类型断言
let someValue: any = "this is a string";
//下面两种方法都可以,不过在TypeScript里使用JSX时,只有 as语法断言是被允许的。
let strLength: number = (<string>someValue).length;
let strLength: number = (someValue as string).length;

ts中特殊符号

ts可以解析es6

数组解构
const [first, second] = [1, 2];

对象解构
const o = {
  name:"小明",
  age: 15
}
const {name, age} = o;

展开操作符
const c = [1, 2];
const d = [3, 4];
const bouthPlus = [1, ...c, ...d, 5];

函数声明
getData({a,b}: {a: string;b: number}): void{
  console.log(a,b);
}
getData({a: "小明", b: 15});

接口

接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

interface LabelledValue{
  readonly size: number;//只读属性,第一次赋值之后不可修改
  label: string;
  color?: string;//可选属性
  [propName: string]: any;//防止额外属性检查是报错
}
function printLabel(labelObj: LabelledValue):{area:number,label:string}{//标明返回值类型,没有返回值写void
 let obj = {area:1,label:"aaa"};
  obj.area = labelObj.size;
  obj.label = labelObj.label;
  return obj;
}
const myobj = {size: 10, label: "this is my house"};
printLabel(myobj);

函数类型
interface SearchFunc{
  (source: string, sunString: string): boolean;
}
let mySearch: SearchFunc;
//函数的参数名不需要与接口里定义的名字相匹配
mySearch = function(src: string,sub: string): boolean{
  const result = src.search(sub);
  return result > -1;
}

可索引的类型
interface StringArray {
  //支持两种索引签名:字符串和数字,数字索引的返回值必须是字符串索引返回值类型的子类型,因为数字索引也是先将数字转化为字符串再去索引
  [index: number]: string;
}
let myArray: StringArray;
myArray = ["a", "b"];
const myStr: string = myArray[0];

类接口
接口描述了类的公共部分
当一个类实现了一个接口时,只对其实例部分进行类型检查,constructor存在于类的静态部分,不在检查的范围内。所以不能把构造函数的接口用于类,可以分别定义构造函数和实例方法所用的接口。
interface ClockConstructor {
  //为构造函数所用
  new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
  //为实例方法所用
  tick(): any;
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface{
  return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
  constructor(h: number, m: number) { }
  tick(){ }
}
class AnalogClock implements ClockInterface {
  constructor(h: number, m: number) { }
  tick() { }
}
const digital = createClock(DigitalClock, 12, 17);
const analog = createClock(AnalogClock, 7, 32);

继承接口
interface Shape {
  color: string;
}
interface PenStroke {
  penWidth: number;
}
interface Square extends Shape, PenStroke {
  sideLength: number;
} 
const square = {} as Square;
square.color = "red";

混合类型
一个接口可以同时作为对象和函数使用,并带有额外的属性
interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}
function getCounter(): Counter {
  const counter = function (start: number){
    console.log(start);
  } as Counter;
  counter.interval = 123;
  counter.reset = function () {
    console.log(1111111);
  };
  return counter;
}
const coun = getCounter();
coun(10);
coun.reset();
coun.interval = 1;

接口继承类
会继承类的成员但不包括实现。当继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现
 class Control {
   private state: any;
 }
 interface SelectableControl extends Control {
   select(): void;
 }
 class Button extends Control implements SelectableControl {
   select(){ }
 }
 class TextBox extends Control {
   select(){  }
 }
 //Image没有继承Control,不存在state私有属性,会报错
 class Image implements SelectableControl {
   select(){}
 }

基于类的面向对象的方式编写代码

//基本类
class Greeter{
    greeting: string;//属性
    constructor(message: string){//构造函数
        this.greeting = message;
    }
    greet(){//方法
        return "Hello," + this.greeting;
    }
}
const greeter = new Greeter("晓红");

//超类
//Ts中,类的成员默认为public
class Animal{
    //私有属性,外部不能访问
    private _pName: string;
    //protected与private相似,不同的是protected成员在派生类中仍然可以访问
    protected _cName: string;
    readonly $gName: string;
    //静态属性,访问需要前面加上类名
    static fName: "欢欢";
    name: string;
    constructor(parentName: string, childName: string, theName: string){
        this._pName = parentName;
        this._cName = childName;
        this.$gName = childName;
        this.name = theName;
    }
    move(distanceInMeters = 0){
        console.log(Animal.fName);
        console.log(`Animal moved ${distanceInMeters}m`)
    }
    //存取器
    get pName(): string{
        return this._pName;
    }
    set pName(newName: string){
        this._pName = newName;
    }
}
//通过extends关键字来继承类
//子类、派生类
class Dog extends Animal{
    constructor(parentName: string,childName: string, name: string){
        //子类构造函数里访问this属性之前,一定要调用super()
        super(parentName, childName, name);
    }
    bark(){
        console.log(this._cName);
        //console.log(this._pName);
        console.log("wang")
    }
    //父类方法重写,实例会调用子类方法
    move(distanceInMeters=2){
        console.log("move方法重写了哦")
        super.move(distanceInMeters)
    }
}
const dog = new Dog("钱多", "钱少", "钱钱");
dog.bark();
dog.move(5);
//dog._pName //parent属性为私有的,外部不能访问
//dog._cName //_cName属性为私有的,外部不能访问
console.log(dog.$gName);
//dog.$gName = "钱真多"; //只读属性不能修改
const pig = new Animal("松松","聪聪","淙淙");
console.log(pig.pName);
pig.pName = "鸿鸿";
console.log(pig.pName);

//抽象类
//抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
abstract class Department {
    constructor(public name: string){}
    printName(): void{
        console.log(this.name);
    }
    abstract printMeeting(): void;//必须在派生类中实现
}
class AccoubtDepartment extends Department {
    constructor(){
        super("雯雯");//派生类的构造函数中必须使用super
    }
    printMeeting(): void{
        console.log("111111")
    }
    generateReports(): void{
        console.log(22222)
    }
}
let department: Department;//允许创建一个对抽象类型的引用
//department = new Department();//不能创建一个抽象类的实例
department = new AccoubtDepartment();//允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
//department.generateReports(); //方法在声明的抽象类中不存在

函数

用于定义行为的地方,可以实现抽象层、模拟类、信息隐藏和模块

function add(x: number, y: number): number{
    return x+y;
}
const myAdd = function(x: number, y: number): number {
    return x+y;
}
add(1,2);
myAdd(3,4);
/**
 * 可选参数
 * 可选参数必须放在必须参数的后面
 */
function buildName(firstName: string,lastName?: string){
    if(lastName){
        return firstName + lastName;
    }else{
        return firstName;
    }
}
console.log(buildName("王"));//王
console.log(buildName("王","三"));//王三
/**
 * 默认参数
 * 默认参数不用放在必须参数后面,不过需要用undefined来占位
 */
function buildName1(firstName = "猪",lastName?: string){
    if(lastName){
        return firstName + lastName;
    }else{
        return firstName;
    }
}
console.log(buildName1("王","八戒"));//王八戒
console.log(buildName1(undefined,"八戒"));//猪八戒
/**
 * 剩余参数
 * 不清楚参数个数时使用
 */
function buildName2(firstName: string,...lastName: string[]){
    return firstName + " " + lastName.join(" ");
}
console.log(buildName2("王","三","四","五"));//王 三 四 五
/**
 * this参数
 * 避免this指向出现问题,可以用es6箭头函数来处理
 */
interface Card {
    suit: string;
    card: number;
}
interface Deck {
    suits: string[];
    cards: number[];
    createCardPicker(this: Deck): () => Card;
}
const deck: Deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function(this: Deck) {
        return () => {
            const pickedCard = Math.floor(Math.random() * 52);
            const pickedSuit = Math.floor(pickedCard / 13);
            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}
const cardPicker = deck.createCardPicker();
const pickedCard = cardPicker();
console.log("card: " + pickedCard.card + " of " + pickedCard.suit);//card: 10 of hearts
/**
 * 重载
 * 函数名相同,参数类型不同、个数不同、返回值类型不同
 */
const suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: {suit: string; card: number }[]): number;
function pickCard(x: number): {suit: string; card: number };
function pickCard(x: any): any {
    if (typeof x == "object") {
        const pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    } else if (typeof x == "number") {
        const pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}
const myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
const pickedCard1 = myDeck[pickCard(myDeck)];
console.log("card: " + pickedCard1.card + " of " + pickedCard1.suit);
const pickedCard2 = pickCard(15);
console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);

装饰器

装饰器是一种特殊类型的声明,本质上就是一个方法,可以注入到类、方法、属性、参数上,扩展其功能
常见的装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器…
装饰器在写法上有:普通装饰器(无法传参)、装饰器工厂(可传参)
添加多个装饰器的执行顺序:属性装饰器>>方法装饰器>>参数装饰器>>类装饰器(用在同一个上则先下后上执行)

具体使用

node里面引入ts

  1. package.json创建:npm init -y
  2. 开发依赖安装:npm i typescript ts-node-dev tslint @types/node -D
  3. 启动脚本
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "ts-node-dev ./src/index.ts -P tsconfig.json --no-cache",
    "build": "tsc -P tsconfig.json && node ./dist/index.js",
    "tslint": "tslint --fix -p tsconfig.json"
  }
  1. 加入tsconfig.json
{
    "compilerOptions": {
        "outDir": "./dist",
        "target": "es2017",
        "module": "commonjs",//组织代码方式 
        "sourceMap": true,
        "moduleResolution": "node", //模块解决策略
        "experimentalDecorators": true, //启用装饰器
        "allowSyntheticDefaultImports": true, //允许es6方式import
        "lib": ["es2015"],
        "typeRoots": ["./node_modules/@types"],
    },
    "include": ["src/**/*"]
}
  1. 创建入口文件./src/index.ts
  2. 运行测试:npm start

常见问题

TypeScript中使用require报cannot find name ’ require’

这个原因是TypeScript不能识别require。

简单但不推荐的做法

如果只是一个文件需要用到require,或者只是一个demo,可以通过下面方式引入require:

declare var require: any

TypeScript 2.x的方法

如果是使用TypeScript2.x,可以使用npm安装typings:

npm install @types/node --save-dev

在tsconfig.json加入:

{
    "compilerOptions": {
        "types": ["node"]
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值