类型系统
众所周知 JS 是一门 弱类型语言,不到执行时都不能确定变量的类型。编码时可以随心所欲反正不报错,一不小心就写出八哥( undefined 警告!)。
1. 静态类型检查
静态类型检查让 TS 在编辑器中披上 强类型语言 的“马甲”,使得开发者在 编码时 就可以 避免大多数类型错误的情况发生,而开发者要做的就 只是声明变量时多写一个符号和一个单词。
当然你也可以在声明变量时 不指定类型 或者使用 any 类型 来达到 JS 的动态类型效果,让 TypeScript 变成 AnyScript ,任性~
let name: string = '陈皮皮'; name = 9527; // 报错 let age: any = 18; age = 'eighteen'; // 不报错
2. 原始类型
TS 在支持 与 JS 基本相同的原始类型 之外,还额外提供了 枚举(Enum)和元组(Tuple) 的支持。
// 枚举 enum Direction { Up = 1, Down, Left, Right } let direction: Direction = Direction.Up; // 元组 let x: [string, number]; x = ['hello', 10]; // 不报错 x = [10, 'hello']; // 报错
3. 智能提示
类型系统 配合 声明文件(关于声明文件我们后面再聊)给我们带来了编辑器中 完善的自动补全智能提示,大大增加了开发效率,也再不会因为拼错变量名或函数名而导致运行时的错误。
修饰符和静态关键字
泪目,是从 C# 那里几乎原汁原味搬过来的一套修饰符和关键字,主要如以下几个:
1. 访问修饰符(public、private 和 protected)
用来 限定类成员的可访问范围。
没有 internal 和 protect internal
没有访问修饰符的封装莫得灵魂!
class Me { public name = '陈皮皮'; // 大家都知道我叫陈皮皮 private secret = '*******'; // 我的秘密只有我知道 protected password = '********'; // 我的支付宝密码会告诉我的后人的 } let me = new Me(); let a = me.name; // 拿到了我的名字 let b = me.secret; // 报错,私有的属性 let c = me.password; // 报错,受保护的属性 class Child extends Me { constructor() { super(); this.name = '陈XX'; this.secret // 报错,无法访问 this.password = '888888'; // 可以访问 } }
2. 静态关键字(static)
用于 定义全局唯一的静态变量和静态函数。
class Whatever { public static origin: string = 'Whatever'; public static printOrigin() { console.log(this.origin); console.log(Whatever.origin); }; } console.log(Whatever.origin); // Whatever Whatever.printOrigin(); // Whatever
3. 抽象关键字(abstract)
用来定义 抽象类或抽象函数,面向对象编程很重要的一环。
abstract class Animal { abstract eat(): void; // 不同动物进食的方式不一样 } let animal = new Animal(); // 报错,法实例化抽象类无 class Dog implements Animal { eat() { console.log('我吃,汪!'); } } let dog = new Dog(); dog.eat(); // 我吃,汪! class Cat implements Animal { // 报错了,没有实现进食的功能 }
4. 只读关键字(readonly)
用来定义只读的字段,使得字段 只能在创建的时候赋值一次。
class Human { name: string; readonly id: number; constructor(name: string, id: number) { this.name = name; this.id = id; } } let human = new Human('陈皮皮', 666666); human.name = '陈不皮'; // 名字可以改 human.id = 999999; // 报错,身份证号码一旦确定不能更改
接口(Interface)
C# 和 Java 的朋友们让我看到你们的双手好吗
接口用于一系列成员的声明,但不包含实现,接口支持合并(重复声明),也可以继承于另一接口。
下面展示几个常见的用法:
1. 扩展原始类型
// 扩展 String 类型 interface String { /** * 翻译 */ translate(): string; } // 实现翻译函数 String.prototype.translate = function () { return this; // 不具体写了,直接返回原字符串吧 }; // 使用 let nickname = '陈皮皮'.translate();
2. 定义类型
interface Human { name: string; // 普通属性,必须有但是可以改 readonly id: number; // 只读属性,一旦确定就不能更改 hair?: number; // 可选属性,挺秃然的 } let ChenPiPi: Human = { name: '陈皮皮', id: 123456789, hair: 9999999999999 }
3. 类实现接口
interface Vehicle { wheel: number; engine?: string; run(): void; } class Car implements Vehicle { wheel: 4; engine: '帝皇引擎'; run() { console.log('小汽车跑得快!') } } class Bike implements Vehicle { wheel: 2; run() { console.log('小黄车冲冲冲!') } }
类型别名(Type)
这是一个比较常用的特性,作用如其名。
类型别名 用来 给类型起一个新的名字。
类型别名和接口很相似,类型别名可以作用于原始类型,联合类型,元组以及其它任何你需要手写的类型,接口支持合并而类型别名不可以。
类型别名同样也 支持扩展,并且可以和接口互相扩展。
// 给原始类型起个小名 type UserName = string; let userName: UserName = '陈皮'; // 还可以是函数 type GetString = () => string; let getString: GetString = () => { return 'i am string'; } let result = getString(); // 创建一个新的类型 type Name = { realname: string; nickname: string; } let name: Name = { realname: '吴彦祖', nickname: '陈皮皮' } // 再来一个新的类型 type Age = { age: number; } // 用上面两个类型扩展出新的类型 type User = Name & Age; let user: User = { realname: '吴彦祖', nickname: '陈皮皮', age: 18, }
联合类型(Union Types)
使用 联合类型 允许你在 声明变量或接收参数时兼容多种类型。
1. 表示一个值可以是几种类型之一
let bye: string | number; bye = 886; // 不报错 bye = 'bye'; // 不报错 bye = false; // 报错
2. 让函数接受不同类型的参数,并在函数内部做不同处理
function padLeft(value: string, padding: string | number) { if (typeof padding === 'string') { return padding + value; } else { return Array(padding + 1).join('') + value; } } padLeft('Hello world', 4); // 返回 ' Hello world' padLeft('Hello', 'I said: '); // 返回 'I said: Hello'
泛型(Generics)
C# 和 Java 的朋友们再次让我看到你们的双手好吗
使用 泛型 可以让一个 类/函数支持多种类型的数据,使用时可以传入需要的类型。
又是一个非常实用的特性,利用泛型可以 大大增加代码的可重用性,减少重复的工作,点赞!
以下是两个常用的用法:
1. 泛型函数
// 这是一个清洗物品的函数 function wash<T>(item: T): T { // 假装有清洗的逻辑... return item; } class Dish { } // 这是盘子 let dish = new Dish(); // 来个盘子 // 盘子洗完还是盘子 // 用尖括号提前告诉它这是盘子 dish = wash<Dish>(dish); class Car { } // 这是汽车 let car = new Car(); // 买辆汽车 // 汽车洗完还是汽车 // 没告诉它这是汽车但是它认出来了 car = wash(car);
2. 泛型类
// 盒子 class Box<T>{ item: T = null; put(value: T) { this.item = value; } get() { return this.item; } } let stringBox = new Box<String>(); // 买一个用来装 String 的盒子 stringBox.put('你好!'); // 存一个 '你好!' // stringBox.put(666); // 报错,只能存 String 类型的东西 let string = stringBox.get(); // 拿出来的是 String 类型
装饰器(Decorator)
这是一个相对比较高级的特性,以 @expression 的形式对类、函数、访问符、属性或参数进行额外的声明。
对类做预处理
export function color(color: string) { return function (target: Function) { target.prototype.color = color; } } @color('white') class Cloth { color: string; } let cloth = new Cloth(); console.log(cloth.color); // white @color('red') class Car { color: string; } let car = new Car(); console.log(car.color); // red
命名空间(namespace)
命名空间用来定义标识符的可用范围,主要用于解决重名的问题,对于项目模块化有很大的帮助。
1. 对相同名字的类和函数进行区分
// pp 命名空间 namespace pp { export class Action { public static speak() { cc.log('我是皮皮!'); } } } // dd 命名空间 namespace dd { export class Action { public static speak() { cc.log('我是弟弟!'); } } } // 使用 pp.Action.speak(); // 我是皮皮! dd.Action.speak(); // 我是弟弟!
2. 对接口进行分类
namespace Lobby { export interface Request { event: string, other: object // ... } } namespace Game { export interface Request { event: string, status: string // ... } } // 用于 Lobby 的请求函数 function requestLobby(request: Lobby.Request) { // ... } // 用于 Game 的请求函数 function requestGame(request: Game.Request) { // ... }
声明文件(Declaration Files)
声明文件,即以 d.ts 作为后缀的代码文件,用来声明当前环境中可用的类型。
声明文件这一特性对于 TypeScript 来说是 极其重要 的,代码编辑器中的智能提示等特性都依赖于声明文件。
可以发现目前大多数 第三方 JavaScript 库 都有声明文件,声明文件让这些库在代码编辑器中也可以 拥有类型检查智能提示等特性,使用体验 Max 。
完
标签:TypeScript,string,let,篇文章,类型,报错,讲透,class,name From: https://www.cnblogs.com/tuyile006/p/17013280.html