一、什么是TypeScript
TypeScript 是一种由微软开发的自由和开源的编程语言,它是 JavaScript 的一个超集,扩展了 JavaScript 的语法。
1,JavaScript VS TypeScript
a, TypeScript与JS的区别
TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
b,TypeScript相比JS的优势
· 优势一:类型化思维方式,使开发更加严谨,提前发现错误,减少改bug时间
· 优势二:类型系统提高了代码可读性,并使维护和重构代码更加容易
· 优势三:补充了接口、枚举等开发大型应用时JS缺失的功能
2,特性:
- 跨平台:TypeScript 编译器可以安装在任何操作系统上,包括 Windows、macOS 和 Linux
- ES6特性:TypeScript 包含计划中的 ECMAScript 2015(ES6)的大部分特性,例如:箭头函数
- 面向对象的语言:TypeScript 提供所有标准的 OOP 功能,如类、接口和模块
- 静态类型检查:TypeScript 使用静态类型并帮助在编译时进行类检查。因此,你可以在编写代码时发现编译时错误,而无需运行脚本
- 可选的静态类型:如果你习惯了 JavaScript 的动态类型,TypeScript 还允许可选的静态类型
- DOM、BOM操作:可以使用 Typescript 来操作 DOM 以添加或者删除客户端网页元素
let img = document.querySelector('#image') as HTMLImageElement// 对于 DOM 以及 BOM的操作,建议使用 javascript
二、TypeScript 安装
// 需要安装提前安装npmnpm install -g typescript//查看版本tsc -v// 如果需求编译时使用命令:tsc filename.ts
三、举个例子
1,创建项目文件夹tsDemo
2,新增一个html文件
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Learning TypeScript</title></head><body><script src="hello.js"></script></body></html>
3,新增一个ts文件
alert('hello world in TypeScript!');
4,编译这个ts文件
tsc hello.ts
5,双击tsDemo/index.html文件
四、基础知识
1,类型
ts的一大特色就是可以在不编译的情况下报错,就是因为她有类型批注这个功能,比如
// 基础数据类型批注let isDone: boolean = false; // 布尔值let decLiteral: number = 6; // 数字let name: string = "bob"; // 字符串let list: number[] = [1, 2, 3]; // 数组1let list: Array<number> = [1, 2, 3]; // 数组2let x: [string, number] = ['hello', 10]; // 元组enum Color {Red, Green, Blue} // 枚举let c: Color = Color.Green;let notSure: any = 4; // 任意值notSure = "maybe a string instead";notSure = false;function warnUser(): void { // 空值 void一般表示函数无返回值alert("This is my warning message");}let u: undefined = undefined; // undefined类型let n: null = null; // null类型// Never类型function error(message: string): never { // 返回never的函数必须存在无法达到的终点throw new Error(message);}function fail() { // // 推断的返回值类型为neverreturn error("Something failed");}function infiniteLoop(): never { // 返回never的函数必须存在无法达到的终点while (true) {}}
2,断言
当你遇到你比TypeScript更了解某个值的详细信息的时候。比如之前设置了any的值
let someValue: any = "this is a string";let strLength: number = (<string>someValue).length; // 方法1let strLength: number = (someValue as string).length; //方法2 :推荐,因为当你在TypeScript里使用JSX时,只有as语法断言是被允许的。
3,函数声明
type C = { a: string, b?: number }function f({ a, b }: C): void {// ...}
4,接口
interface Point { // 混合类型x: number; // 普通属性readonly y: number; // 只读属性color?: string; // 可选属性reset(): void; //函数}// 函数类型interface SearchFunc {(source: string, subString: string): boolean;}let mySearch: SearchFunc;mySearch = function(source: string, subString: string) {let result = source.search(subString);return result > -1;}// 索引类型interface StringArray {[index: number]: string;}// 接口继承interface Shape {color: string;}interface Square extends Shape {sideLength: number;}// 类类型,implements关键字用来实现类类型接口interface ClockInterface {currentTime: Date;}class Clock implements ClockInterface {currentTime: Date;constructor(h: number, m: number) { }}
5,类
class Greeter {greeting: string;constructor(message: string) {this.greeting = message;}greet() {return "Hello, " + this.greeting;}}let greeter = new Greeter("world");
class Animal {name: string;constructor(theName: string) { this.name = theName; }move(distanceInMeters: number = 0) {console.log(`${this.name} 移动 ${distanceInMeters}米.`);}}class Snake extends Animal { // 作为派生类,通过extends关键字继承Animal类。constructor(name: string) { super(name); }move(distanceInMeters = 5) {console.log("滑行中...");super.move(distanceInMeters);}}// 派生类包含了一个构造函数,它必须调用super(),// 它会执行基类的构造函数。 而且,在构造函数里访问this的属性之前,我们一定要调用super()。// 这个是TypeScript强制执行的一条重要规则。class Horse extends Animal {constructor(name: string) { super(name); }move(distanceInMeters = 45) {console.log("奔跑中...");super.move(distanceInMeters);}}let sam = new Snake("蛇三");let tom: Animal = new Horse("马四");sam.move();tom.move(34);
// alert('hello world in TypeScript!');class User {static age = 23; // 静态属性,存在于类本身上,访问时不需要实例化readonly id: number; // 可以访问,但是一旦确定不能修改protected username: string; // 自身和子类可以访问,但是不能外部修改private password: string; // 外部包括子类不能访问,也不可以修改public info: string; // 默认的,可以去掉public修饰符constructor(id: number, username: string, password: string, info: string) {this.id = id;this.username = username;this.password = password;this.info = info;}getInfo() {console.log(this.id, `this.id`);console.log(this.username, `this.username`);console.log(this.password, `this.password`);console.log(this.info, `this.info`);}//可以通过public方法修改private属性setPassword(password: string) {if (password.length >= 6) {this.password = password;}}}class Vip extends User {getInfo2() {console.log(this.id, `this.id`);console.log(this.username, `this.username`);// console.log(this.password,`this.password`); //报错,私有类console.log(this.info, `this.info`);}}console.log(`User.age`,User.age);let user1 = new User(1, '张三', '123456', '打工人');user1.getInfo();let vip = new Vip(1, '李四', '000000', '人上人');vip.getInfo2();console.log(user1.id, `user1.id;`);// console.log(user1.username,`user1.username;`); // 报错,保护类 只有自身和子类可以访问// console.log(user1.password,`user1.password;`); // 报错,私有类,只有自身可以访问console.log(user1.info, `user1.info;`);
abstract class Department {constructor(public name: string) {}printName(): void {console.log('部门名称: ' + this.name);}abstract printMeeting(): void; // 必须在派生类中实现}class AccountingDepartment extends Department {constructor() {super('会计'); // 在派生类的构造函数中必须调用 super()}printMeeting(): void {console.log('会计部门在每周一上午10点开会.');}generateReports(): void {console.log('报告生成中...');}}let department: Department; // 允许创建一个对抽象类型的引用// department = new Department(); // 错误: 不能创建一个抽象类的实例department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值department.printName();department.printMeeting();// department.generateReports(); // 错误: 方法在声明的抽象类中不存在
class Point {x: number;y: number;}interface Point3d extends Point {z: number;}let point3d: Point3d = {x: 1, y: 2, z: 3};
6,函数
function add(x: number, y: number): number {return x + y;}// 完整的函数类型定义let myAdd: (x:number, y:number) => number =function(x: number, y: number): number { return x + y; };// 类型推断let myAdd = function(x: number, y: number): number { return x + y; };// 可选参数function buildName(firstName: string, lastName?: string) {if (lastName)return firstName + " " + lastName;elsereturn firstName;}let result1 = buildName("Bob"); // works correctly nowlet result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameterslet result3 = buildName("Bob", "Adams"); // ah, just right// 默认参数function buildName(firstName: string, lastName = "Smith") {return firstName + " " + lastName;}let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameterslet result4 = buildName("Bob", "Adams"); // ah, just right// 剩余参数function buildName(firstName: string, ...restOfName: string[]) {return firstName + " " + restOfName.join(" ");}let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;// 重载:为同一个函数提供多个函数类型定义来进行函数重载,根据参数不同调用不同函数let 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 {// Check to see if we're working with an object/array// if so, they gave us the deck and we'll pick the cardif (typeof x == "object") {let pickedCard = Math.floor(Math.random() * x.length);return pickedCard;}// Otherwise just let them pick the cardelse if (typeof x == "number") {let pickedSuit = Math.floor(x / 13);return { suit: suits[pickedSuit], card: x % 13 };}}let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];let pickedCard1 = myDeck[pickCard(myDeck)];alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);let pickedCard2 = pickCard(15);alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
7,泛型
// 泛型函数function identity<T>(arg: T): T {return arg;}// 泛型接口interface GenericIdentityFn<T> {(arg: T): T;}// 泛型类class GenericNumber<T> {zeroValue: T;add: (x: T, y: T) => T;}let myGenericNumber = new GenericNumber<number>();myGenericNumber.zeroValue = 0;myGenericNumber.add = function(x, y) { return x + y; };// 泛型约束interface Lengthwise {length: number;}function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length); //扩展中表示参数是有length这个原型方法的return arg;}let logs = loggingIdentity(['abc'])
