简介
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。

区别

准备工作

1.安装 TypeScriptnpm install -g typescript
验证 TypeScript
tsc -v
编译 TypeScript 文件
tsc helloworld.ts

一般工作流程

TypeScript 初体验 

hello.ts
function greet(person: string) {return 'Hello, ' + person;
}console.log(greet("TypeScript"));
编译后 tsc hello.ts
"use strict";
function greet(person) {return 'Hello, ' + person;
}
console.log(greet("TypeScript"));观察以上编译后的输出结果,我们发现 person 参数的类型信息在编译后被擦除了。TypeScript 只会在编译阶段对类型进行静态检查,如果发现有错误,编译时就会报错。而在运行时,编译生成的 JS 与普通的 JavaScript 文件一样,并不会进行类型检查。

基础类型

let isDone: boolean = false;let count: number = 10;let name: string = "semliker";const sym = Symbol();
let obj = {[sym]: "semlinker",
};console.log(obj[sym]); // semlinker let list: number[] = [1, 2, 3];
// ES5:var list = [1,2,3];Enum 类型(反向映射)
enum Direction {NORTH,SOUTH,EAST,WEST,
}let dir: Direction = Direction.SOUTH;//1  从0开始
or
let dir = Direction[0];//'SOUTH'
or
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];  // 'Green'
or
let colorName: string = Color[Color.Green];  // 'Green'联合类型
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

对象的类型——接口

interface Person {name: string;age: number;
}let tom: Person = {name: 'Tom',age: 25
};
定义的变量比接口少或多了一些属性是不允许的继承interface LengthInterface {length: number}interface WidthInterface {width: number}interface HeightInterface {height: number}interface RectInterfaceextends LengthInterface,WidthInterface,HeightInterface {// length:number// width:number// height:numbercolor: string}let rect: RectInterface = {length: 10,width: 20,height: 30,color: 'red',}

高级类型

交叉类型
interface DogInterface {run():void
}
interface CatInterface {jump():void
}
let pet: DogInterface & CatInterface = {
// 看上去和接口多继承很像,但有一点区别。继承可以有自己的属性,交叉不行。run(){},jump(){},
};联合类型
// 现在有两种形状,area函数用来计算每种形状的面积。
interface Square{kind: "square";size: number;
}
interface Rectangle{kind: "rectangle",width: number,height: number,
}
type Shape = Square | Rectangle;
function area(s: Shape) {switch (s.kind) {case "square":return s.size * s.size; // 此区块内,确保只有size属性case "rectangle":return s.height * s.width;}
}
console.log(area({kind:"square",size:10})); // 100
// 现在要添加一个形状:圆形。需要定义接口Circle、为Shape添加联合类型Circle,然后为area函数内增加一个case。但是,如果我们忘了修改area函数,会发生什么?
interface Circle{kind: "circle",r: number,
}
type Shape = Square | Rectangle | Circle;
console.log(area({kind:"circle",r:10})); // undefined,这里并不报错,并不符合我们的预期。我们希望bug能够及时暴露出来,增加程序的稳定性。
做如下改动:
function area(s: Shape) {switch (s.kind) {case "square":return s.size * s.size;case "rectangle":return s.height * s.width;case "circle":return Math.PI * s.r;default:return ((e: any)=>{throw new Error(`没有定义 ${s} 的面积计算方式`)})(s) // 这一步很重要,一定要在这里抛出异常}
}索引类型
当我们使用不存在的索引时,会返回undefined,没有约束(如下代码)。因此我们需要有对索引的约束。
let obj = {a: 1,b: 2,c: 3,
};
function getValue(obj: any,keys: string[]){return keys.map(key => obj[key]);
}
console.log(getValue(obj,["a","b"]));
console.log(getValue(obj,["c","f"])); // 会发现,'f'对应的输出是undefined,没有约束,需要用到索引类型
下面使用索引类型:
function getValue<T,K extends keyof T>(obj: T, keys: K[]): T[K][] { // T[k][]表示,返回值必须是obj中的值组成的列表return keys.map(key => obj[key]); // 此时keys中的元素只能是obj中的键
}
console.log(getValue(obj,["a","b"]));
console.log(getValue(obj,["c","f"])); // 这时就会报错,有了约束 'f' is not in "a" | "b" | "c"
我们来解释一下:这里会用到两个操作符,查询操作符 keyof T 和 访问操作符 T[k](看下面示例)。<T, K extends keyof T> 用到了泛型约束,表示K所约束的参数的值只能是T所约束参数数据中的“键”。
// keyof T
interface Obj{a: number;b: string;
}
let key: keyof Obj; // 此时key表示 'a' | 'b'// T[k]
let value: Obj['a'] // number映射类型可以从旧的类型生成新的类型。比如,将接口中的所有成员变成只读、可选。interface Obj{a: string;b: number;c: boolean;
}
// 将Obj接口中每个成员变成只读属性,生成一个新的接口。
type ReadonlyObj = Readonly<Obj>;  // Readonly是TS内置的映射类型,下同
// Readonly实现原理,利用了索引类型的操作方法
type Readonly<T> = {readonly [P in keyof T]: T[P];
}
再如:
// 将所有属性变成可选
type PartialObj = Partial<Obj>;
// Partial实现原理
type Partial<T> = {[P in keyof T]?: T[P];
}// 获取原类型的子集
type PickObj = Pick<Obj,'a'|'b'>;
// 等同于
interface PickObj {a: string,b: number
}// 将原类型当做新类型的成员
type RecordObj = Record<'x'|'y',Obj>;
// 等同于
interface RecordObj {x: Obj,y: Obj,
}
条件类型
条件类型指由表达式所决定的类型。条件类型使类型具有了不唯一性,增加了语言的灵活性。
T extends U ? X : Y   表示如果类型T可以被赋值给类型U,name结果就赋予X类型,否则赋予Y类型
再如
type TypeName<T> =T extends string ? string :T extends number ? number :T extends boolean ? boolean :T extends undefined ? undefined :T extends Function ? Function :object;type T1 = TypeName<string>;   // T1为字符串类型
type T2 = TypeName<string[]>; // T2为object类型
type T3 = TypeName<Function>; // T3为function类型
type T4 = TypeName<string | string[]>; // T4为 string和object的联合类型
可以用来做什么?
(A | B) extends U ? X : Y
解析为(A extends U ? X : Y) | (B extends U ? X : Y)
可以利用这一特性做类型的过滤,例如:
type Diff<T,U> = T extends U ? never : T;type T5 = Diff< 'a'|'b'|'c', 'a'|'e' >; // 作用是过滤掉第一个参数中的'a' 。T5为 'b' | 'c'联合类型
解析过程:Diff<'a', 'a'|'e'> | Diff<'b', 'a'|'e'> | Diff<'c', 'a'|'e'>never | 'b' | 'c''b' | 'c'
TS内置的条件类型:
Exclude<T, U>  // 从T中剔除可以赋值给U的类型,相当于上面例子中的Diff
Extract<T, U>  // 提取T中可以赋值给U的类型。
NonNullable<T>  // 从T中剔除null和undefined。
ReturnType<T>   // 获取函数返回值类型。
InstanceType<T>  // 获取构造函数类型的实例类型。

内置函数

Exclude<T, U> - 用于从类型T中去除不在U类型中的成员
eg:type T00 =  Exclude<"a" | "b" | "c" | "d","a" | "c" | "f">;
eg:  type T00 = "b" | "d"
let t0:T00 = "b"
console.log(t0)
//在这个例子中,因为用到了Exclude这个条件类型,会尝试寻找在T类型中有,但在U类型中没有的成员,最后将获取到的Union类型"b" | "d"赋给T00Extract<T, U> - 用于从类型T中取出可分配给U类型的成员 交集
eg:type T01 =  Exclude<"a" | "b" | "c" | "d","a" | "c" | "f">;
re: type T01 = "b" | "d"NonNullable<T> - 通过运行NonNullable,清除了undefined类型成员
eg:type notNull  = NonNullable<number | string | null | undefined>
re:   type T01 = type notNull = string | numberReturnType<T> - 通过ReturnType,返回了范型参数T的返回值类型
eg:type T11 = ReturnType<()=>string>
re:  type T11 = stringInstanceType<T> - 获取构造函数函数类型的返回类型
eg:type NewType = InstanceType<new (name: string) => { name: string; age: number }>;
re:
type NewType = {name: string;age: number;} Partial<T>
eg:type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
re:
interface User {name: string;sex: string;age: number;
}
type NewType = Partial<User>;
re:
type NewType = {name?: string | undefined;sex?: string | undefined;age?: number | undefined;
}Readonly<T> - 将 T 中的所有属性设置为只读
type Readonly<T> = { readonly [P in keyof T]: T[P]; }
eg:
interface User {name: string;sex: string;age: number;
}
type NewType = Readonly<User>;re:
type NewType = {readonly name: string;readonly sex: string;readonly age: number;
}Required<T> - 将 T 中的所有属性设置为必须
type Required<T> = { [P in keyof T]-?: T[P]; }
-? 表示取消可选
eg:
interface User {name: string;sex?: string;age?: number;
}
type NewType = Required<User>;re:
type NewType = {name: string;sex: string;age: number;
}Pick<T, K> - 从 T 中,选择一组位于 K 中的属性type Pick<T, K extends keyof T> = {[P in K]: T[P];
};
eg:
interface User {name: string;sex: string;age: number;
}
type NewType = Pick<User, 'name' | 'sex'>;re:
type NewType = {name: string;sex: string;
}Extract<T, U> - 从 T 中提取可分配给 U 的类型
type Extract<T, U> = T extends U ? T : never;
eg:
interface User {name: string;sex: string;age: number;
}
type NewType = Extract<keyof User, 'name' | 'sex'>;re:
type NewType = "name" | "sex"Omit<T, K> - 构造一个属性为 T 的类型,但类型 K 中的属性除外
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
eg:
interface User {name: string;sex: string;age: number;
}
type NewType = Omit<User, 'name' | 'sex'>;re:
type NewType = {age: number;
}Parameters<T> - 获取函数类型的参数,返回的是个元组
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
eg:
interface User {name: string;sex: string;age: number;getFamily: (name: string) => User[];
}
type NewType = Parameters<User['getFamily']>;re:
type NewType = [string]大小写type NewType = Uppercase<'aaa'>; // AAA  全大写
type NewType = Lowercase<'AAA'>; // aaa   全小写
type NewType = Capitalize<'aaa'>; // Aaa   首字母大写
type NewType = Uncapitalize<'AAA'>; // aAA   首字母小写

demo(基于vue3和typescript)

import { ref, Ref, watch } from 'vue'interface Range {min?: number,max?: number
}interface Result {count: Ref<number>,inc: (delta?: number) => void,dec: (delta?: number) => void,set: (value: number) => void,reset: () => void
}export default function useCount(initialVal: number, range?: Range): Result {const count = ref(initialVal)const inc = (delta?: number): void => {if (typeof delta === 'number') {count.value += delta} else {count.value += 1}}const dec = (delta?: number): void => {if (typeof delta === 'number') {count.value -= delta} else {count.value -= 1}}const set = (value: number): void => {count.value = value}const reset = () => {count.value = initialVal}watch(count, (newVal: number, oldVal: number) => {if (newVal === oldVal) returnif (range && range.min && newVal < range.min) {count.value = range.min} else if (range && range.max && newVal > range.max) {count.value = range.max}})return {count,inc,dec,set,reset}
}
<template><div class="homePage"><HelloWorld :msg="year"/><div><div>{{ width }}</div><div>{{ height }}</div></div><div><div>{{count}}</div><button @click='inc'>+</button><button @click='dec'>-</button><button @click='set(100)'>set 100</button><button @click='reset'>reset</button></div></div>
</template><script  lang="ts">
import { defineComponent, reactive, ref, toRefs,watch } from "vue";
import HelloWorld from './components/HelloWorld.vue'
import useCount  from './hooks/useCount'
import useWindowResize from "./hooks/useWindowResize";
export default defineComponent({components: {HelloWorld},setup() {const year = ref(0);const user = reactive({ nickname: "xiaofan", age: 26, gender: "女" });const state = reactive({ nickname: "xiaofan", age: 20 });const { count, inc, dec,set,reset } = useCount(10);setInterval(() => {year.value++;user.age++;state.age++;}, 1000);// 修改age值时会触发 watch的回调watch(() => state.age,(curAge, preAge) => {console.log("新值:", curAge, "老值:", preAge);},{ deep: true });const stopWatchRoom = watch(year, (newVal, oldVal) => {console.log("新值1:", newVal, "老值1:", oldVal);});const { width, height } = useWindowResize();setTimeout(()=>{stopWatchRoom()}, 3000)return {count,inc,dec,set,reset,width,height,year,// 使用reRefs...toRefs(user),...toRefs(state),};},
});
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

TypeScript散文相关推荐

  1. 超简单的react和typescript和引入scss项目搭建流程

    1.首先我们先创建一个react项目,react官网也有react项目搭建的命令 npx create-react-app my-app cd my-app 2.安装我们项目需要的样式依赖,这个项目我 ...

  2. 老码农绝密:使用 TS(TypeScript) 的 10 大理由

    最近,小编读了一篇名为<放弃 TypeScript 的 7 个非常好的理由>,这篇文章的阅读量不低.里面有些观点确实有趣,不过在这里我要向你介绍使用 TypeScript 的 10 个理由 ...

  3. 设置WebStorm像VSCode一样每行代码结尾自动格式化加入“;”分号(JavaScript、TypeScript格式化)

    Ctrl+Shift+S→编辑器→Code Style→JavaScript或TypeScript→Punctuation 1.每行代码结尾自动加上;分号: Use(下拉框选Use)semiconlo ...

  4. 为TypeScript项目生成API文档

    为TypeScript项目生成文档 使用typedoc为TypeScript项目生成API文档. 1. 使用typedoc生成HTML文档 需要安装 typedoc. npm i typedoc 可以 ...

  5. TypeScript 1

    TypeScript 的由来 TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准. TypeScript 由微软开发的自由和开源的编程语言. TypeSc ...

  6. TypeScript学习笔记之 接口(Interface)

    在java中,接口是用来定义一些规范,使用这些接口,就必须实现接口中的方法,而且接口中的属性必须是常量. javascript中是没有接口的概念的.所以TypeScript在编译成 JavaScrip ...

  7. c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法

    c# typescript by Leonardo Carreiro 莱昂纳多·卡雷罗(Leonardo Carreiro) 在任何IDE中从C#,Java或Python代码获取TypeScript接 ...

  8. 如何在React中使用Typescript

    TypeScript can be very helpful to React developers. TypeScript对React开发人员可能非常有帮助. In this video, Ben ...

  9. 使用Typescript的巧妙React上下文技巧-不是Redux

    by Bill Girten 比尔·吉尔滕(Bill Girten) 使用Typescript的巧妙React上下文技巧- 不是 Redux (Clever React context tricks ...

  10. 使用TypeScript映射和条件类型使React组件更出色

    by Deepu K Sasidharan 通过Deepu K Sasidharan 使用TypeScript映射和条件类型使React组件更出色 (Make your React component ...

最新文章

  1. hello是c语言中的变量吗,C语言hello world详解
  2. python3 异步错误 asyncio.Semaphore RuntimeError: Task got Future attached to a different loop
  3. verilog基础—规范化参数定义parameter
  4. iOS之Socket的使用-AsyncSocket
  5. Android之把app作为独立的module导入其他项目遇到的坑
  6. eladmin代码自动生成_如何让Mybatis自动生成代码
  7. ajax的学多久,ajax第二天学习
  8. java中的pane,Java中scroll pane的使用(一)– 动态改变其client的大小 | 学步园
  9. 推荐系统实战第一部分 协同过滤
  10. “华为搜索”正海外内测;苹果5亿美元和解“降速门”;Firefox隐藏HTTPS | 极客头条...
  11. 拓端tecdat|Python中的Lasso回归之最小角算法LARS
  12. 通州区机器人比赛活动总结_超燃!通州区中小学机器人大赛圆满落幕
  13. 深圳宝安学区房_查查吧深圳学区地图
  14. 永善县黄华镇大永高速通车了
  15. 解决回溯法 - 回溯到底是个什么东西(含有大量经典例题加详细分析)
  16. 图像的模式(RGB和CMYK)、通道(8位、16位、32位)分别有什么作用
  17. 如何做数据竞赛·优秀案例学习(DC03)
  18. 判断单链表成环与否?
  19. 微信小程序蓝牙使用总结
  20. Python入门--爬取淘宝评论并生成词云

热门文章

  1. 基于centos7制作安装好环境的iso镜像文件
  2. 2019年六项扣除 个税计算器
  3. 【码上实战】【立体匹配系列】经典AD-Census: (5)扫描线优化
  4. android studio 初始化项目加载时间过长或失败问题解决
  5. 安卓性能优化——布局性能优化
  6. 还不了解外贸流程?这一篇就够了(小声bb)
  7. 处理猪舌须知小窍门-滋阴润燥好良方-菜椒滑猪舌
  8. TideSec远控免杀学习二(Evasion模块+veil)
  9. 如何在地图上按地址搜索位置
  10. 日志过滤实体中的属性