typescript---快速入门

什么是TS

TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,具有可选的类型并可以编译为JavaScript。从技术上讲TypeScript就是具有静态类型的 JavaScript 。 TypeScript 编写的文件以.ts为后缀,用 TypeScript 编写 React 时,以 .tsx 为后缀。

安装typescript

命令:npm/cnpm install -g typescript
检查是否安装成功:tsc -v

新建文件

(1)文件目录:创建index.ts
(2)里面写点内容,然后编译tsc index.ts

可能遇到的问题

启动成功后,文件会多出编译后的index.js文件,如果在第一次启动tsc index.ts(文件名)后发现报错,如下图,

在这里插入图片描述

  • 此时重新以管理员的身份重新打开编辑器,打开终端,然后输入命令:
get-ExecutionPolicy (显示restricted:表示是受限制的);
set-ExecutionPolicy RemoteSigned;(设置)
get-ExecutionPolicy(再次输入,会显示RemoteSigned)

(3)配置文件

//文件tsconfig.json里配置=====根据需求配置
{
    "compilerOptions": {
        // none、'commonjs','amd','system','es6','es2015','esnext'
        "module": "es2015",//指定模块化标准,如果要合并多个模块化的代码就要使用"system"
        "target": "es2015",//用来编译什么语法,
        "strict": true,
        // "lib":[]//指定项目中要使用的库
        "sourceMap": true,
        "outDir":"./dist",//编译后文件在的目录
        "outFile":"./dist/app.js",//将代码合成为一个文件
        "allowJs":true,//是否编译js
        "checkJs":true,//是否检查js
        "removeComments": false,//是否在编译后带有注释
        "noEmit": true,//不生成编译文件。
        "noEmitOnError":true,//当有错误时,不生成编译文件
        "alwaysStrict": true,//用来设置编译后的文件使用严格模式
        "noImplicitAny":true,//不允许隐式的any类型
        "noImplicitThis": true,//不允许不明确的的this
        "strictNullChecks": true,//严格的检查空值;
    },
    "exclude": ["node_modules"],//不包含
    "include": ["./src/**/*"],//src目录下都可以编译

}

typescript语法

  1. 类型声明:
语法:
let 变量:类型;
let 变量:类型=;

表示声明一个变量str,同时指定它的类型为string,也就是说只能赋值字符串的值,其它会报错,如下声明的变量

var str: string = "你好";
var num: number = 2;

2.可以使用|来表示多个类型

let yan: boolean | string;
yan= true;
yan = "hello"

3.any表示的是任意类型,使用ts时,不建议用any类型,相当于没有类型

let d: any;
 d = 10;
 d = "dddd";
 d = true;
  1. unknown表示未知类型
let e: unknown;
e = true;
e = 'hello';
let s: string;
//s=e 这样不能直接赋值,因为定义的e是未知类型,如果是any就可以
//可判断
if (typeof e === 'string') {
    s = e
}
语法:
  变量 as 类型  ==>  s = e as string
  <类型>变量    ==>  s = <string> e
  1. void用来表示空,没有返回值
function fn():void{

}
  1. object对象
语法:{属性名:属性值,属性名:属性值}

(1)、在属性的后面加上?,表示属性是可选的,赋值时可写age也可不写

let d:{str:string,age?:number};
 d={str:"董"};

(2)、[proname:string]:any表示任意类型的属性;

//声明时没有定义age、gender属性,加了[proname:string]:any赋值时是可以的
let c:{str:string,[proname:string]:any};
c={str:"dong",age:12,gender:"男"};
  1. 设置函数结构类型声明:
语法:
functon fn(参数:类型,参数:类型):类型(返回值的类型){
}
(形参:类型 ,形参:类型 ,....)=>返回值;
function getRest(a: number, b: number): number {
    return a + b
}
getRest(2, 5);
let m:(a:number,b:number)=>number;
  1. 数组Array

(1) 、表示字符串数组

 let f:string[];
f=["a","d"]

(2)、表示数字数组

let g:Array<number>
g=[1,2,3]

(3)元组,就是固定长度的数组

let v:[string,number];
v=["22",234]
  1. &表示同时
let j:{str:string}&{age:number};
j={str:'dong',age:12}
  1. 类型别名
type mytype=1|2|3|4|5|6;
let k:mytype;
let n:mytype;
k=4;
n=2;

类型推论

如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。

//比如下面的代码,没有写类型,但是它的值是一个字符串,所以再次赋值为数字7是会报错的
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;//报错

类-------接口

类:定义了一件事物的抽象特点,包含它的属性和方法

1、创建一个类,运用了static静态

class Person{
   name:string="孙悟空";
   num:number=18;
   static age:number=20;//静态属性
  // 加上static只能用类Person去调用
   static sayhello(){
       console.log("age")
   }
   sayHi(){
       console.log(this.num)
   }
}
const per=new Person;
Person.sayhello();
per.sayHi()//实例调用

2、抽象方法使用抽象类abstract和继承extends

class Animal {
    namestr: string;
    age: number;
    // 构造函数会在对象创建时调用
    //抽象方法使用abstract开头,子类必须对抽象方法进行重写
 abstract constructor(namestr: string, age: number) {
        this.namestr = namestr;
        this.age = age;
    }
  abstract say(): void;
}
//这里运用了继承========extends ============
class Dong extends Animal {
//当子类用了constructor时,需要用super去复用父类的
    constructor(newname: string, age: number) {
        super(newname, age);
    }
    say() {
        console.log("汪汪")
    }
}
const minzi = new Dong('wang', 6);
console.log(minzi);
minzi.say();

3、修饰属性public、pricate、protected

public 修饰的属性可以在任意位置访问,默认值
private 私有属性 ,私有属性只能在类的内部进行访问
protected受包含的属性,只能在当前和当前类使用


 class Animal {
    private namestr: string;//私有属性
    protected age: number;
    public gender:number;
    constructor(namestr: string, age: number,gender:number) {
        this.namestr = namestr;
        this.age = age;
        this.gender=gender;
    }
    getName(){
        return this.namestr;
    }
    setname(value:string){
       this.namestr=value;
    }
    say(){
      console.log(this.age)//6
    }
}
const per = new Animal('wang', 6,5);
per.setname("dong")
per.say();
console.log(per.getName())//==>dong
console.log(per.gender)//5
console.log(per.namestr)//报错

4、接口

接口是一种规范的定义,它定义了行为和动作的规范, 定义好接口,用来定义类中包含哪些属性和方法,可以重复申明,接口中的属性不能有实际的值

接口合并

interface myInterface{
    name:string,
    age:number,
}
interface myInterface{
    gender:string,
}
const obj:myInterface={
    name:"ddd",
    age:2,
    gender:'男'
}

函数类型接口

interface encrypt{
    (key:string,value:string):string;
}
var md5:encrypt=function(key:string,value:string):string{
    return key+value;
}
md5('dong','zhang')

类与接口类型

interface Anmimal{
    name:string;
    eat(str:string):void;
}
class Dog implements Anmimal{
    name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(food:string){
        console.log(this.name+'吃'+food)
    }
}
var dng=new Dog('柯基')
dng.eat('肉')

接口继承

// 接口继承
interface Persen{
    eat():void;
}
// PersonOne继承Persen的接口===
interface PersonOne extends Persen{
   work():void;
}
// web实现PersonOne的类,所以需要包含它们的方法==
class web implements PersonOne{
    public name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(){
        console.log(this.name+'吃肉---');
    }
    work(){
        console.log(this.name+'做作业')
    }
}

let p=new web('小红')
p.eat();//小红吃肉---
p.work();//小红做作业

5、泛型

可以支持不指定数据类型,传入的参数和返回的数据一直,在定义函数或者是类时,如果遇到类型不明确就可以使用泛型

function fn<K>(a: K): K {
    return a
}
let result=fn(10)//不指定泛型,TS可以自动对类型进行推测
let result1=fn<string>('dong')//指定类型string
console.log(result,result1)//=>10,dong

function fn2<K,T>(a: K,b:T): K {
    console.log(b);//=>bu,dong
    return a
}
let result3=fn2(10,"bu")
let result4=fn2<number,string>(23,'dong')

类的泛型

class MinClass<T>{
    public list: T[] = [];
    add(value: T): void {
        this.list.push(value)
    }
    min(): T {
        var minNum = this.list[0];
        for (var i = 0; i < this.list.length; i++) {
            if (minNum > this.list[i]) {
                minNum = this.list[i]
            }
        }
        console.log(minNum)//88
        return minNum;
    }
}
var mi=new MinClass<number>();//这里定义的参数是number
mi.add(99);
mi.add(88);
mi.min()

6、命名空间

内部模块,主要用于组织代码,避免命名冲突,一个模块里可能会有多个命名空间,各个命名空间里的相同类名或者接口不冲突

// 用了命名空间相当于私有空间,
namespace A {
    interface Anmimal {
        name: string;
        eat(str: string): void;
    }
    //里面的方法或者类需要`export`暴露出去
    export class Dog implements Anmimal {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        eat(food: string) {
            console.log(this.name + '吃' + food)
        }
    }
}
// 实例化时用命名的A去获取
var d = new A.Dog('zhangsan');
d.eat('肉')

7、装饰器

装饰器:是一种类型的声明,它能够被附加到类声明,方法、属性或参数上,可以修改类的行为。通俗讲:就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。分两类:普通装饰器(无法传参)、装饰器工厂(可传参)

  1. 普通装饰器(无法传参)
function logClass(params:any){
   console.log(params)//@logClass如果没有传参数params就是当前的类HttpClient
//  扩展属性和方法==
params.prototype.apiUrl='动态扩展的属性';
params.prototype.run=function(){
    console.log("跑步=====")
}
}
@logClass
class HttpClient{
    constructor(){}
    getDate(){}
}
var http:any =new HttpClient();
console.log(http.apiUrl);//动态扩展的属性
http.run();//跑步=====
  1. 装饰器工厂(可传参)
function logClass(params: string) {
    console.log(params)
    //params传过来的参数====(我是来学ts的)
    return function (target: any) {
        // target就是类HttpClient 
        target.prototype.apiUrl = params;
    }
}
@logClass('我是来学ts的')//传的参数
class HttpClient {
    constructor() {}
    getDate() {}
}
var http: any = new HttpClient();
console.log(http.apiUrl);//动态扩展的属性
  1. 修改方法及属性装饰器
//类装饰器修改属性及方法数据
function logClass(target: any) {
//target=>类HttpClient 
    return class extends target {
        str: any = '我是修改后的属性';
        getDate() {
            console.log(this.str)//我是修改后的属性
        }
    }
}
// 属性装饰器=====
function logParams(params: any) {
    console.log(params)//传的参数(我是属性装饰器---)
    return function (target: any, attr: any) {
        console.log(target);//=>类
        console.log(attr);//属性=>str
        target[attr] = params;//加上这个会显示str'我是属性装饰器---'
    }
}
@logClass
class HttpClient {
    @logParams('我是属性装饰器---')
    public str: string | undefined;
    constructor() {
        this.str = '我是构造函数里的str'
    }
    getDate() {
        console.log(this.str)
    }
}
var http = new HttpClient();
http.getDate()
console.log(http.str);//=>我是修改后的属性
  1. 方法装饰器及修改方法传参的类型

function getMethods(params: any) {
    return function (target: any, methods: any, desc: any) {
        console.log(target);
        console.log(methods);//方法的名字
        console.log(desc.value);//=>getDate()方法===
        // 扩展属性和方法=====
        target.str = '修改后的===';
        target.run = function () {
            console.log('run')
        }
        //  修改装饰器的方法,把装饰器方法里面传入的所有参数改为string类型
        //保存当前的方法
        var oMethods = desc.value;
        //  改变参数的类型===
        desc.value = function (...args: any[]) {
            args = args.map((value) => {
                return String(value);
            })
            console.log(args)
            oMethods.apply(this,args)
        }
    }
}
class HttpClient {
    public str: string | undefined;
    constructor() {
        // this.str = '我是构造函数里的str'
    }
    @getMethods('http://www.baidu.com')
    getDate(...args: any[]) {
        console.log(args);   
    }
}
var http: any = new HttpClient();
http.run();
console.log(http.str);
http.getDate(123, 123)

有了ts,好像就不用写typeof了,也不用检查拿到的数据是不是string、number、undefined、null了,给程序带来了稳定性和可预测性,方便debug。😊😊😊😊😊😊

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值