TypeScript迅速入门与应该知道

TypeScript应该知道

简述:TypeScript基础知识。


链接

TypeScript 官网:http://www.typescriptlang.org

TypeScript 在线编译器:http://www.typescriptlang.org/play

TypeScript 项目地址:https://github.com/Microsoft/TypeScript

TypeScript 中文网:https://www.tslang.cn/

TypeScript 中文gitbook:https://github.com/zhongsp/TypeScript

引文:

对于入门学习来说,不应该,也不能去学习过于深入的内容。以下是TypeScript入门应该知道的基础内容:

  • TypeScript的基础类型
  • 变量的各种声明形式
  • 接口、类、函数、存取器的定义和一些使用形式
  • 迭代器
  • 模块的导入与导出

[注]
Ionic 2+使用Angular2+,而Angular2+使用TypeScript,因此,不管是学习Angular2,还是Ionic,首先都应该对上诉内容有一定的掌握。

其他可选:

  • 声明合并
  • 命名空间
  • 泛型的定义和使用
  • 装饰器(需要有基本的了解,Ionic项目常见)
  • 高级类型(交叉类型、联合类型等)

TypeScript的基础类型

要啃一啃

  • 布尔值 boolean
  • 数字 number
  • 字符串 string
  • 数组 Array
  • 元组 Tuple
  • 枚举 enum
  • 任意值 any
  • void
  • Null 和 Undefined
  • Never

说明:

  1. 所有未定义变量的初始值都是undefined
  2. TypeScript变量的声明形式如:let 变量名:变量类型,实际声明则形如:let flag: boolean
  3. let 是var的替代品,其声明的变量有更严谨的作用域,能有效避免var带来的各种问题。

基础类型示例:

//作用:添加按钮到body标签中
let putButton = function (text:string,info:any){
    let button = document.createElement("button");
    let p = document.createElement("p");
    button.textContent = text;
    document.body.appendChild(button);
    document.body.appendChild(p);
    button.onclick = function() {
        alert(info);
    };
}

//boolean类型
let flag:boolean;
let flag_1:boolean = false;
putButton("let flag:boolean;",flag);
putButton("let flag_1:boolean = false;",flag_1);

//number
let PI : number = 3.1415926535897932384626433;//圆周率
putButton("number>>>圆周率PI",PI);
putButton("number>>>圆直径5,周长",5*PI);

//字符串
let str_double_quotes:string = "双引号声明string";
let str_single_quote :string = '单引号声明string';
let str_accent :string = `上点号声明string`;//可内嵌${表达式}
putButton("string>>>"+str_accent+"${5*8}",`5*8的值:${5*8}`);

//数组,两种声明方式
let nums: number[] = [1, 2, 3,4];
let numList: Array<number> = nums;
putButton("数组[1,2,3,4]",numList.toString());

//元组Tuple
let dog:[string,number] = ["蝴蝶犬",5];//元组是一个数组,允许元素类型不同
dog[3] = "岁了";//数组越界不报错,因为"dog"是string|number联合类型
// dog[4] = false;//错误
putButton("元组Tuple",dog[0]+dog[1]+dog[3]);

//enum 枚举
enum Xiyouji{
    唐僧,悟空,八戒=3,沙僧,白龙马
}//手动指定索引下标
let tangseng:Xiyouji = Xiyouji.唐僧;
let wukong:string = Xiyouji[1];//手动声明索引,左边索引从零开始
let shaseng:string = Xiyouji[4];//手动声明索引,右边索引依次增加
putButton("enum>>>西游记",wukong);

//any 任意值
let 水牛:any = "shuiniu";
let shuiniu:number = 100;
水牛 = shuiniu;
putButton("any>>>水牛",水牛);

//void 空值,只能为null或undefined
let v:void = null;
v = undefined;
function f():void{ return v};//空返回值,有点奇怪
putButton("void>>>",f());

//null和undefined,默认情况下null和undefined是所有类型的子类型。其他类型的值一般都可以赋给它们。
let undef: undefined = null;
let nul: null = undefined;
putButton("null和undefined","null和undefined是所有类型的子类型");

//Never类型表示的是那些永不存在的值的类型
//never类型是任何类型的子类型,但没有类型是never的子类型
// 这意味着never可以赋值给任何类型,但没有任何类型可以赋值给never类型(除了never本身之外)
let neve:never ;//初值undefined
let go:string = neve;
//never表示永远不存在值的类型
function trueWhile():never{
    while (true){}
}
putButton("never>>>",go);

详细请参考:https://www.tslang.cn/docs/handbook/basic-types.html


变量声明

说明:下文代码中的setElement(xxx,xxx)方法,其实现如下:

/此方法的作用:在body标签中追加指定元素和内容
function setElement(elementName:string,contentText:any){
    let e = document.createElement(elementName);
    e.textContent = contentText;
    document.body.appendChild(e);
}

关键字

应该有所了解并能使用,开始时可以不必深入研究。

  • var
  • const
  • let

var声明的变量,可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问。也就是说即使是这样也可以正常执行:

gog = "迷你";
var gog;
if (true){
    alert(gog);
}

const 常量,与let具有相同的作用域。
let声明的变量具有块级作用域,也就是说被try,if,while等块包围时,外部不能访问。可以有效避免var定义的各种问题。JavaScript本身具备let,IE11支持,参考:https://msdn.microsoft.com/zh-cn/library/dn263046(v=vs.94).aspx

遍历一个字符串数组,var的声明:

function forStrVar():void {
    let str: string[] = ["草原", "一万只尼玛兽呼啸而过"];
    for (var i = 0; i < str[0].length; i++) {
        setElement("p", "------" + str[0].charAt(i) + "------");
        //里层第一次循环完毕后,i==str[1]的长度-1,覆盖外层循环,导致外层循环条件为false,于是外层循环只执行一次。
        for (var i = 0; i < str[1].length; i++) {
            setElement("p", str[1].charAt(i));//contents += str.charAt(i);//var声明的i互相干架。
        }
    }
}

改为let声明后正常。

数组的解构

应该了解,但可以先囫囵吞枣

解构数组,构造数组。

//数组的解构
let input = [1, 2];
let [first, second] = input;//相当于使用索引声明两个变量first = input[0];second = input[1];
setElement("h1","数组的解构");
setElement("p",first+"----"+second);
//交换值
[second,first] = [first,second];
setElement("p",first+"----"+second);
//...的形式声明剩余变量。
let [o,,u,...t] = [1,2,3,4,5];//一些元素可以不必命名
setElement("p",o+"----"+u+"----"+t);

对象的解构

应该了解,但可以先囫囵吞枣

类似数组的解构。JavaScript对象就是json。

let abc = {a: "foo", b: 12, c: "bar"}//符号:在此处的作用不是声明类型,而是声明属性的值。
let {a,b} = abc;//虽然abc的属性更多。

function中使用解构

function()中也可以使用解构

type C = { a: string, b?: number };//符号?:表示声明一个可选的属性
function f({ a, b }: C): void {//....}

展开数组

应该了解。

在声明中展开一个数组的值构成一个新的数组:

let num_a = [1,2,3];
let num_b = [...num_a,4,5,"hao"];//使用“...数组”展开为元组
let num_c = [num_a,4,5,"hao"];//展开
setElement("h1","展开数组")
setElement("p",num_b);

展开对象

应该了解

在声明中展开一个对象的值构成一个新的数组:

let dog = {id:1,name:"dog"};
let home = {father:"da",monther:"mo",me:"hao",...dog,name:"狗狗阿里"};//使用"...对象"写法展开。后声明的属性允许覆盖
setElement("h1","展开对象");
setElement("p",home.name);

更多请参考:https://www.tslang.cn/docs/handbook/variable-declarations.html


接口、类、函数的定义和一些使用形式

需要基本掌握。

  • 接口允许多继承
  • 类不允许多继承,但类允许多实现
  • 类通过set,get关键字声明存取器
  • 接口对象的声明形式为let shou = <接口>{//…},而不是let shou = new 接口{//…};

以下定义Voice(声音)接口,Animal抽象类,Dog类,Cat类:

它们之间的关系关键字
Voiceinterface
Animal —>> Voiceabstract , class , implement
Dog —>> Animalclass , extend
Cat —>> Animalclass , extend
Homeclass

ICFMoreH.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>接口、类、函数的定义和一些使用形式</title>
    <script src="ICFMore.js"></script>

</head>
<body>
    <input type="button" value="千年京巴" onclick="jingbaClick()"/>
    <p></p>
    <p>
        输入日期:
    <input id="month-day" type="text" value=""/>
    <button onclick="okClick()">确定</button>

    </p>
</body>
</html>

ICFMore.ts:


/**
 * 接口、类、函数的定义和一些使用形式
 */

//声音接口
interface Voice {
    getLanguage():string;//默认public
    speak(content:any):void;
}
abstract class Animal implements Voice{
    getLanguage(): string{
        return "动物世界通行语";
    }
    abstract speak(content?: any): void;//可选参数。可选声明的形式为“修饰符 名称?:类型”
}
class Dog extends Animal{//private和protected不能出现在模块或命名空间元素上。此处不允许用来修饰类

//     constructor(public name?:string,public id:string,public age:number,public sex:string){//可选参数不允许在固定参数之前
//         super();
//     }
    //此处使用public,为this.xx = xx的简写。会自动创建并赋值属性
    constructor(public id:string,public age:number,public sex:string,public name?:string){//不允许多个构造函数实现。。。
        super();
    }
    speak(content: any): void {
        alert(content);
    }
    getLanguage(): string{
       return "汪星语";
    }
}
class Cat extends Animal{
    private _name: string;
    speak(content?: any): void {
        alert("喵喵!");
    }
    //getter,setter存取器
    set name(name :string){
        this._name = name;
    }
    get name():string{
        return this._name;
    }
}
class Home{
    // let dogB:Dog = new Dog("001",4,"雌","go");//不能在此使用let,var声明
    private catA:Cat = new Cat();
    private dogA:Dog = new Dog("001",4,"雌","go");
    private readonly tag?:string = "山顶洞人的home";//可选的、只读属性的home。可选声明的形式为“修饰符 名称?:类型”

    protected go(){

    }
    play(monthDay:any){//默认public
        this.catA.name="我是一只喵";//需要使用this.属性来访问,直接访问不到
        this.dogA.name = "我是一只汪";
        console.log(monthDay);
        monthDay = parseInt(monthDay,10);//字符串转成十进制数字
        let select = monthDay % 2;

        switch (select){
            case 0:
                alert("Today,我 play with "+this.dogA.name);
                break;
            case 1:
                alert("Today,我 play with "+this.catA.name);
                break;
            default:
                alert("未知日期,我 play with "+this.dogA.name);
                break;
        }
    }
}
//北京哈巴
function jingbaClick(){
    let jingba:Dog = new Dog("京巴001",4,"雌");
    jingba.speak("汪汪!");
}
function okClick(){
    let home: Home = new Home();
    let day = (<HTMLInputElement> document.getElementById("month-day")).value;//HTMLElement中没有value属性。需要类型断言(强转)
    // let day = (document.getElementById("month-day") as HTMLInputElement).value;//;类型断言的另一种方式。
    home.play(day);
}

另一个示例——尼玛兽

接口多继承相关。

interface SayName{
    sayName(name:string):void;
}
interface Paobu{
    pao():void;
}
class Nima implements SayName,Paobu{
    sayName(name: string): void {
        alert("我是"+name);
    }

    pao(): void {
        alert("跑了一万公里");
    }
}
//允许多继承
interface Shou extends SayName,Paobu{
    shache():void;
}
//尼玛兽
class NimaShou implements Shou{
    shache(): void {
        alert("尼玛兽刹车了");
    }

    sayName(name: string): void {
        alert("我是尼玛兽");
    }

    pao(): void {
        alert("尼玛兽奔跑了一万公里");
    }
}

// class NimaShenshou extends Nima,NimaShou{}//Classes can only extend a single class

var shou = <Shou>{};//接口对象的形式。
shou.sayName = function (name:string = '兽类') {
    alert(name);
}
shou.sayName("兽类接口");
var go = <Paobu>{ pao: function () {
    alert("跑步");
}}
go.pao();

迭代器

  • for
  • while

for…of 和 for…in:

  • for…in 迭代对象的 键 的列表
  • for…of 迭代对象的 键 对应的值

具体区别:

let list = [4, 5, 6];

for (let i in list) {
    console.log(i); // "0", "1", "2",索引
}

for (let i of list) {
    console.log(i); // "4", "5", "6",值
}

//普通写法
for (let i = 0; i < list.length; i++) {
    let num = list[i];
    console.log(num);// "4", "5", "6",值
}

do…while和while

  • while 直接循环{}中代码
  • do…while 先执行了do块的代码

具体区别:

let list = [1,2,3,4,5];
//箭头函数表达式。能够在函数创建时绑定this,避免一些问题。常规写法则是咋函数调用时绑定,这时的this可能并非预期。 
let wheel_do = ()=>{
    let i =0;
    do {
        // console.log(list[i]);
        htmlLog(list[i]);
        i++;//先执行了do块的代码
    }while (i<list.length);
};
let wheel = () => { //简单来说就是解决this指向不明的问题。
    let i = 0;
    while (i < list.length) {
        htmlLog(list[i]); 
        i++;
    }
}
let htmlLog = function (text:any) { 
    let e = document.createElement("p");
    e.textContent = text;
    document.body.appendChild(e);
}
// wheel_do();
wheel();

更多请参考:https://github.com/Mingyueyixi/TypeScript/blob/master/doc/handbook/Iterators%20and%20Generators.md

关于箭头函数:

https://github.com/Mingyueyixi/TypeScript/blob/master/doc/handbook/Functions.md

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arrow_functions

关于TypeScript的this:

https://github.com/Mingyueyixi/TypeScript/blob/master/doc/wiki/this-in-TypeScript.md


模块的导入与导出

常用,需要掌握

关键字:

  • import
  • export

导入与导出涉及模块,需要有加载器才能运行起来。比如服务于Node.js的CommonJS和服务于Web应用的Require.js。

模块:

  • ECMAScript 2015引入。TypeScript沿用。
  • 自身有作用域。需要通过导入、导出才能够引入与使用其他模块中的内容。
  • TypeScript与ECMAScript 2015中,任何包含顶级 import 或者 export 的文件(.ts文件,而不是一个类或接口)
    都被当成一个模块。

导出的方式

1. 声明时直接导出
export let goHome :string = "go home";
export interface Hot{
//...
}
2. 使用export{}语句导出
interface Hot{
//...
}
export{Hot};
//export{Hot as HotDog};//Hot作为HotDog导出,重命名。as在类型断言也有相似用法。
3. 重新导出

用于导出另一个模块的部分内容,或将多个模块一起导出。

导出一个模块的部分内容:

HotHome.ts

export let dog = "热狗";
export interface Hot{
    eat();
}

DogHome.ts

export class Dog{
    eat(){
        alert("eat ");
    }
}
export {dog as nimaDog} from "./HotHome";//从HotHome模块中导出dog,重命名为尼玛dog

导出之后使用import使用它:

TestHotDog.ts

import {nimaDog as nimashou} from "./DogHome";//从DogHome模块中导入nimadog,重命名为尼玛兽
class Test{
    go(){
        alert(nimashou);
    }
}
多个模块一起导出:

语法:export * from "module"

示例:

export * from "./HotHome"; 
export * from "./DogHome";
4. 默认导出
  • 一个模块仅可以有一个默认导出。其声明形式为:export default xxx
  • 类和函数的使用默认导出后,在导入时可以省略名字。

使用默认导出:

JQuery.d.ts

declare let $: JQuery;
export default $;

导入:

App.ts

import $ from "JQuery";
$("button.continue").html( "Next Step..." );

导入的方式

导入的方式和导出类似

1. 直接导入声明
import {Hot} from "./HotHome"; //从HotHome模块导入export声明的Hot接口
2. 导入声明并重命名
import {dog as nimaDog} from "./HotHome";` //从HotHome模块导入export声明的dog,重命名为nimaDog
3. 所有export声明全部导入
import  * as yy from "./DogHome";//从HotHome模块导入所有的export声明,命名为,使用时通过yy调用。
let nimashou = yy.nimaDog; 
4. 具有副作用的导入

官方文档这么描述:

尽管不推荐这么做,一些模块会设置一些全局状态供其它模块使用。 这些模块可能
没有任何的导出或用户根本就不关注它的导出。 使用下面的方法来导入这类模块:

import "./my-module.js";

导入与导出综合示例:

使用export关键字导出写好的模块:

Email.ts

export class Email {
    public static dress:string;
    public static content:string;
    sendTo(dress:string,content:string){
        console.log("/n寄往:"+dress + "/n内容:"+content);
        Email.dress = dress;
        Email.content = content;
    }
    received(){
        console.log("/n收到:"+Email.dress+"/n内容:"+Email.content);
        return {d:Email.dress,c:Email.content};
    }
}

使用import关键字导入Email模块,并使用它:

Biaoju.ts

import { Email } from "./Email";
/**
 * 镖局
 */
export class Biaoju {
    /**
     * 押镖:货物
     * 押镖时要发邮件通知委托人
     */
    yabiao(huowu:string){
        let email :Email = new Email();
        email.sendTo("北京","我们今天开始押镖。"+Date.now());
        console.log("押镖:"+huowu);
    }

}

Jiefei.ts

import {Email as Feigechuanshu} from "./Email";//导入Email模块,重命名为飞鸽传书
/**
 * 劫匪
 */
export class Jiefei{
    /**
    * 收到邮件之后,开始打劫
    */
    dajie(){
        let feige:Feigechuanshu = new Feigechuanshu();
        let xin:{d:string,c:string} = feige.received();//收到信
        console.log("收到飞鸽传书,来自:"+xin.d+"内容:"+xin.c);
        alert(`${shanzhai},呔,留下买路财!`);

    }
}
export let shanzhai = "劫机山寨";

继续引入模块,将劫匪和镖局模块引入:

testGo.ts

import {Biaoju} from "./Biaoju";
import {Jiefei} from "./Jiefei";

let biaoju_A = new Biaoju();
let jiefei_shanzaiA = new Jiefei();

biaoju_A.yabiao("百年大萝卜");
jiefei_shanzaiA.dajie();

[注] 生成的是符合CommonJS规范的JavaScript代码,不能直接跑。需要加载器。

更多请参考:https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Modules.md

使用module声明模块

TypeScript使用module声明模块,就能够直接跑了。

Tuzi.ts

module Tuzi{
export class Tu{
    speak(){
        alert("我是一只兔子");
    }
}
}

调用模块:

TestTuzi.ts

let tu = new Tuzi.Tu();
tu.speak();

使用时,要引入所有编译的JavaScript文件:

TestTuziH.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>兔子</title>
</head>
<body>
<script src="Tuzi.js"></script>
<script src="TestTuzi.js"></script>
</body>
</html>

运行,弹出一个“我是一只兔子”对话框。


作为入门参考,一般到此结束。

以下是可选内容链接:

声明合并:

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Declaration%20Merging.md

命名空间

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Namespaces.md

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Namespaces%20and%20Modules.md

泛型的定义和使用:

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Generics.md

装饰器:

其形式为:@xxx,能够被附加到类声明,方法,访问符,属性或参数上。

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Decorators.md

高级类型

交叉类型、联合类型等。

https://github.com/zhongsp/TypeScript/blob/master/doc/handbook/Advanced%20Types.md


本文相关代码地址:

https://git.oschina.net/mingyueyixi/typejs/tree/master/page/00-tsBook

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值