type-script入门

1. 安装

  1. 下载vcode
    按ctrl+k ctrl+l,然后搜索格式化文件,设置格式化的快捷键
  2. npm install typescript@2.9.2 -g
    npm install ts-node@7.0.0 -g
    记下ts-node可执行文件路径
    image.png
  3. 配置文件(.vscode/launch.json)
{
     "configurations": [
         {
         "name": "ts-node",
         "type": "node",
         "request": "launch",
         "program": "这里写之前ts-node的安装路径",
         "args": ["${relativeFile}"],
         "cwd": "${workspaceRoot}",
         "protocol": "inspector"
         }
     ]
 }

2. ts文档

1. 第一步

创建greeter.ts文件,按下保存的快捷键,再命令行进入当前文件夹运行tsc greeter.ts,这样就转成js文件

function greeter(person: string) {
    return "Hello, " + person;
}

let user = "Jane User"; 

console.log(greeter(user));  
// 若传的不是string会报错,但undefined可以通过

2. 接口

interface可以让你规定一个对象必须要有哪些属性,同时在函数传的参数里也只能用这些属性

interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person: Person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}

let user = { firstName: "Jane", lastName: "User" };

console.log(greeter(user));

3. 类

类可以支持函数

class Student {
    fullName: string;
    firstName: string;
    constructor(firstName: string, public middleInitial: string, public lastName: string) {
        this.firstName = firstName
        this.fullName = firstName + " " + middleInitial + " " + lastName;
    }
}

interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person : Person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}

let user = new Student("Jane", "M.", "User");

console.log(greeter(user));

public等于帮你申明一个变量并在constructor里写上this.lastName = lastName,所以Student有四个属性:fullName、firstName、middleInitial、lastName,但在函数greeter里只能用接口里有的属性,不能用fullName,除非你接口用Student

3. 实现一些简单函数

1. 找较小数

function min(a: number,b: number): number{
    if(a>b){
        return b
    }else{
        return a
    }
}
console.log(min(2,1))

意思是返回值也必须是number

2. 重载

function add(a: string, b: string): string;
function add(a: number, b: number): number;
function add(a: any, b: any): any {
    return a+b
}
console.log(add('a','d'));

a和b只支持同时是string或者同时是number类型

3. 定义数组的方式

  • 第一种
let a: number[] = [1,2,3]; // 意思是由number组成的数组
  • 第二种
let b: Array<number> = [1,2,3]  

3. 元祖

已知元素数量和类型情况下的数组可以用元祖

let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error

3. 判断是否能结婚

interface human{
    gender: string;
}
function merry(a: human,b :human): [human, human]{
    if(a.gender !== b.gender){
        return [a,b]
    } else{
        throw new Error('性别相同不能结婚')
    }
}
let a = {gender: 'male'}
let b = {gender: 'female'}

console.log(merry(b,b));
  • 枚举
    给性别规定只能是male和female
enum Gender {
    Male,
    Female
}

interface human{
    gender: Gender;
}
function merry(a: human,b :human): [human, human]{
    if(a.gender !== b.gender){
        return [a,b]
    } else{
        throw new Error('性别相同不能结婚')
    }
}
let a = {gender: Gender.Male}
let b = {gender: Gender.Female}

console.log(merry(a,b));

4. 实现一些命令行工具

1. process.argv

在1.ts文件里写

#!/usr/bin/env ts-node  // 蛇棒
console.log(process.argv)  
// 在命令行里运行`./1.ts abc`,process.argv 就是这一行的内容
console.log(123);

第一行加了蛇棒,在命令行运行node ./1.ts的时候就不用加node,直接运行./1.ts即可
运行npm init -y,在目录里添加package.json文件
运行npm i -D @types/node,安装process的包

2. 加法

给ts加es6的语法库,在目录下创建tsconfig.json文件,去网上复制tsconfig.json的默认格式,然后在里面添加"es2015"

// tsconfig.json
{
    "compilerOptions": {
        "lib": [
            "es2015"
        ]
    }
}
  • add.ts
#!/usr/bin/env ts-node

let a: number = parseInt(process.argv[2])
let b: number = parseInt(process.argv[3])
if(Number.isNaN(a) || Number.isNaN(b)){
    console.log('必须是数字')
} else {
    console.log(a+b)
}

命令行运行./add.ts 1 2

#!/usr/bin/env ts-node
{
  let a: number = parseInt(process.argv[2])
  let b: number = parseInt(process.argv[3])
  if(Number.isNaN(a) || Number.isNaN(b)){
    console.log('必须是数字')
    process.exit(1)
  }

  console.log(a+b)
  process.exit(0)
}

成功的退出返回0,不成功的返回1

3. 族谱

#!/usr/bin/env ts-node

{
    class Person{
        public Children: Person[] = [];
        constructor(public name: string){}
        addChild(child: Person): void {
            this.Children.push(child)
        }
        introduceFamily(n: number): void {
            let pre = '----'.repeat(n-1)
            console.log(pre + this.name)
            this.Children.forEach(child=>{
                child.introduceFamily(n+1)
            })
        }
    }

    let a = new Person('jpj')
    let b = new Person('son')
    let c = new Person('daughter')
    a.addChild(b)
    a.addChild(c)
    a.introduceFamily(1)
}

下面将n改为可选参数

#!/usr/bin/env ts-node

{
    function createPre(n: number): string {
        return '----'.repeat(n)
    }
    class Person{
        public Children: Person[] = [];
        constructor(public name: string){}
        addChild(child: Person): void {
            this.Children.push(child)
        }
        introduceFamily(n?: number): void {
            n = n || 1
            console.log(createPre(n-1) + this.name)
            this.Children.forEach(child=>{
                child.introduceFamily(n+1)
            })
        }
    }

    let a = new Person('jpj')
    let b = new Person('son')
    let c = new Person('daughter')
    a.addChild(b)
    a.addChild(c)
    a.introduceFamily(1)
}

在n后加个?,就变为可选参数

5. 模版字符串

let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.

6. 枚举

enum Color {Red, Green, Blue}
let c: Color = Color.Green;

enum Color {Red = 0, Green, Blue}
let colorName: string = Color[2];

console.log(colorName);  // 显示'Blue'

7. any

// 前面不加any,这样用编译时就会报错
let notSure = 412312;
console.log(notSure.substr())

// 加个any就会在执行时报错
let notSure: any = 412312;
console.log(notSure.substr())

// 在不知道数组类型时也可以用any
let list: any[] = [1, true, "free"];
list[1] = 100;

8. void

// void表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 `void`:
function warnUser(): void {
    alert("This is my warning message");
}

// 声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined和null:
let unusable: void = undefined;

9. 可选属性

加了?疑问号之后,就变为可选属性,如果不加疑问号的话在写createSquare的参数的时候就必须同时传color和width

interface SquareConfig {
  color?: string;
  width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
  let newSquare = {color: "white", area: 100};
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

let mySquare = createSquare({color: "black"});

10. 接口

1. 只读属性

interface Point {
    readonly x: number;
    readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
// 赋值
  • 还有只读的数组
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!

赋新值也不行,除非用类型断言重写

a = ro as number[];

做为变量使用的话用 const,若做为属性则使用readonly。

2. 额外的属性检查

如果你能够确定这个对象可能具有某些做为特殊用途使用的额外属性

interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

3. 接口也可以定义函数

interface SearchFunc {
  (source: string, subString: string): boolean;
}

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

11. 函数

let myAdd: (baseValue: number, increment: number) => number =
    function(x: number, y: number): number { return x + y; 
};

函数也不会固定参数的名字,只要类型匹配就可以

  • 剩余参数
    在你不确定参数个数时
function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
console.log(employeeName);

12. 泛型

一个函数想让传入参数类型和return类型相同时,可以用泛型

function identity<T>(arg: T): T {
    console.log(T.length)  // 报错
    return arg;
}

这样你传的是什么类型,输出就必须是什么类型

function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length);  // 这样就不会报错
    return arg;
}

13. 声明合并

1. 合并接口

interface Box {
    height: number;
    width: number;
}

interface Box {
    scale: number;
}

let box: Box = {height: 5, width: 6, scale: 10};

13. 类型兼容性

1. 函数

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;

y = x; // OK,可以把x赋给y
x = y; // Error,不能把y赋给x
console.log(x(123123))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容