跳到主要内容

6 篇博文 含有标签「TypeScript」

查看所有标签

interface的作用

  1. 描述对象的形状
  2. 对类的一部分行为进行抽象

    下面的文章主要围绕着上面的两部分进行讲解。

一、描述对象的形状

注意:下面的interface之间的元素是通过分号进行分割的。interface 后面跟的名字大小写都可以。

interface person {
name: string;
music: string;
}
let person: person = {
name: 'justin',
music: 'test'
}
  • 通过interface定义的对象,属性的个数不可多页不可少,如果非要少的话,可以采取下面的这种形式。可选属性
interface person {
name: string;
music?: string;
}
let person: person = {
name: 'justin',
}
  • 通过interface定义的对象,如果想出现自由属性,可以通过下面的这种方式。
interface person {
name: string;
music?: string;
[propName: string]: any;
}
let person: person = {
name: 'justin',
sex: 'fox'
}
  • 通过readonly定义只读属性
interface person {
readonly id: number;
name: string;
music?: string;
[propName: string]: any;
}
let person: person = {
id: 123456,
name: 'justin',
sex: 'fox'
}

person.id = 666; // 此处会报错

JustinTypeScript阅读需 1 分钟

配置VScode自动生成TS文件

  • 生成ts配置文件
tsc --init
  • 激活输出路径 image.png

  • 配置保存即输出到指定路径

  1. 点击终端下的运行任务 image.png
  2. 点击typescript image.png
  3. 点击tsc监视

TS中的基本数据类型

boolean类型

let flag: boolean = true;
flag = false;

number类型

let num: number = 666;
num = 777;

string类型

let str: string = '666';
str = '777';

array类型

// 方式1
let arr: number[] = [1,2,3];
// 方式2
let arr2: Array<number> = [6,7,8];

元组类型(tuple)

// 元组类型
let arr: [number,string,boolean] = [1,'60',true];

枚举类型

// 枚举类型
enum Flag{color1 = 'blue',color2 = 'pink'};

let flag: Flag = Flag.color2;

console.log(flag);

任意类型any

// 任意类型
let num: any = 666;
num = 'test';
num = true;

undefined类型

// undefined类型
let num: undefined;
console.log(num);

null类型

let num: null;
num = null;

void类型

  • 表示方法没有任何返回类型
function run(): void{
console.log('run');
}

never类型

表示无法到达终点的函数,例如死循环或者抛出异常。

function test(): never {
throw new Error('错误');
}

TS的函数类型

基本形式

function test(name: string,age: number): string{
return `${name} ---- ${age}`
}
test('nihao',666);

可选参数

在JS中,函数定义的参数可传也可不传,但是在TS中是必须传递的,如果不传需要配置可选参数。

function test(name: string,age?: number): string{
return `${name} ---- ${age}`
}
test('nihao');

默认参数

下面的例子中的number是默认参数。

function test(name: string,age: number=20): string{
return `${name} ---- ${age}`
}
test('nihao');

剩余参数

function sum(...arg: number[]): number{
return arg.reduce((pre,cur) => pre + cur,0)
}
sum(1,2,3,4)

函数重载

在JS中一旦出现同名方法在同一作用域的情况下,下面的会覆盖上面的,但是在TS中则存在重载的情况。

  • 注意:下面的any并不是说可以传递任意类型。
function test(name: string): string;

function test(age: number): string; // 这里的any其实并不是真正的any,必须传递上面的两种类型之一,反之报错 function test(str: any): string{ if (typeof str === 'string') { return '姓名' + str; } else { return '年龄' + str; } } test('里斯');


## TS中的类
### 类中属性和方法的定义
```ts
class Person{
name: string;
constructor(n: string) {
this.name = n;
}
run() :void {
console.log(this.name);
}
}

const p = new Person('张三');
p.run();

TS中实现继承

TS中实现继承主要用到了extends和super两个关键字。

class Person{
name: string;
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在学习`
}

}

class child extends Person{ constructor(name: string) { super(name); } }

const c = new child('小明'); console.log(c.run());


### 类中的修饰符
* public: 自身可以调用,子类可以调用,实例可以调用
```js
class Person{
public name: string;

constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在学习`
}
}

const p = new Person('张三');
console.log(p.name);
  • protected: 自身可以调用,子类可以调用
class Person{
protected name: string;

constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在学习`
}
}

class Child extends Person{

constructor(name: string) {
super(name)
}
run2(): void{
console.log(this.name);
}
}

const c = new Child('666');
console.log(c.run());
  • private:只有自身能够访问
class Person{
private name: string;

constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在学习`
}
}

const p = new Person('张三');
p.name // 报错

注意:如果不写类成员修饰符默认是public.

静态属性和静态方法

  • 通过static关键词定义静态属性
class Person{
name: string;
constructor(name: string){
this.name = name;
}

run() {
console.log(this.name);
}
static work() {
console.log('这是类的静态方法');
}
}

const p = new Person('张三');

// p.work() // 报错
Person.work();
  • 静态方法只能调用静态属性不能调用实例属性
class Person{
name: string;
static age: number = 18;
constructor(name: string){
this.name = name;
}

run() {
console.log(this.name);
}
static work() {
console.log('这是类的静态方法');
console.log('年龄是:',Person.age);
}
}

const p = new Person('张三');

Person.age;
Person.work();

多态

多态指的是父类定义一个方法不去实现,让子类去实现,每一个子类有不同的表现。

class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(): void {
console.log('这是父类的eat');
}
}

class Cat extends Animal {
name: string;
constructor(name: string) {
super(name)
this.name = name;
}
eat(): void {
console.log('这是子类的多态:',this.name);

}
}
const c = new Cat('小猫');
c.eat();

抽象类

用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体的实现且必须在派生类中实现。抽象方法只能放在抽象类中。

  1. 抽象类无法进行具体的实例化
abstract class Animal{
abstract eat(): void;
}
const a = new Animal() // 直接报错
  1. 抽象类的子类必须实现抽象类中的抽象方法
abstract class Animal {
abstract eat(): void;
}
class cat extends Animal {
eat(): void {
console.log(666);
}
}
const c = new cat();
c.eat()

TS中的接口

接口的存在也是为了定义标准。

属性接口

interface fullname {
firstName: string;
secondName: string;
}
function getName (name: fullname) {
console.log(`${name.firstName} + '---' + ${name.secondName}`);
}
const obj = {
firstName: '小',
secondName: '明'
}
getName(obj);

接口的可选属性

interface fullname {
firstName: string;
secondName?: string;
}
function getName (name: fullname) {
console.log(`${name.firstName} + '---' + ${name.secondName}`);
}
const obj = {
firstName: '小',
// secondName: '明'
}
getName(obj);

函数类型的接口

interface encrypht {
(key: string,value: string): string;
}
const md5: encrypht = function md5(key: string, value: string): string {
return key + value;
}
console.log(md5('1','2'));

可索引接口

这个接口主要是对数组和对象的约束。

  • 对数组的约束
interface useArr {
[index: number]: string;
}

const arr: useArr = ['1','2']
  • 对对象的约束
interface useObj {
[index: string]: string;
}
const obj: useObj = {
name: '张三',
age: '666'
}

类类型接口

类类型接口存在的意义主要是对类进行约束。

interface Animal {
name: string;
eat(str: string): void;
}
class Cat implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(str: string): void {
console.log(this.name + str);
}
}
const cat = new Cat('小猫咪');
console.log(cat.eat('玉米'));

接口拓展

接口拓展指的是接口可以继承另一个接口。

interface Animal {
eat(): void;
}
interface Person extends Animal {
work(): void;
}
class people implements Person {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log('eat');
}
work() {
console.log('work');
}
}
const p = new people('小张');
p.eat()
p.work()

继承+实现

interface Animal {
eat(): void;
}
interface Person extends Animal {
work(): void;
}
class Programer {
name: string;
constructor(name: string) {
this.name = name;
}
coding(): void {
console.log(this.name + '在写代码');
}
}
class people extends Programer implements Person {
name: string;
constructor(name: string) {
super(name);
this.name = name;
}
eat() {
console.log('eat');
}
work() {
console.log('work');
}
}
const p = new people('小张');
p.coding();

TS中的泛型

泛型可以支持不特定的类型。

泛型定义

function getData<T>(value: T): T {
return value;
}

console.log(getData<string>('123'));
console.log(getData<number>(123));

类的泛型

class MinClass<T> {
list: T[] = [];

add(num: T) {
this.list.push(num);
}

min(): T {
let minNum = this.list[0];
for (let v of this.list) {
if (v < minNum) {
minNum = v;
}
}
return minNum;
}
}
const m = new MinClass<number>();

泛型接口

  • 写法1
interface configFn {
<T>(value: T): T;
}

const fn: configFn = function<T>(value: T): T {

return value;
}

console.log(fn<string>('666'));
  • 写法2
interface configFn<T> {
(value: T): T;
}

function getData<T>(value: T): T {
return value;
}

const myGetData: configFn<string> = getData;

myGetData('20')

泛型类实现泛型接口(用于逻辑复用)

泛型类快速实现泛型接口的方法

  1. 定义好初始结构
class MongoDb<T> implements DBI<T> {

}
  1. 光标悬浮然后点击快速修复 image.png

  2. 点击实现接口 image.png

  • 经典实例
interface DBI<T> {
add(info: T): boolean;
update(info: T): boolean;
delete(id: number): boolean;
get(id: number): any[];
}

/**
* @description: 要实现泛型接口的类也必须是泛型类
* @param {*}
* @return {*}
*/
class MysqlDb<T> implements DBI<T> {
add(info: T): boolean {
throw new Error("Method not implemented.");
}
update(info: T): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}

class MongoDb<T> implements DBI<T> {
add(info: T): boolean {
console.log(info);
return true;

}
update(info: T): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}

}

class User {
username: string | undefined;
password: string | undefined;
}

const u = new User();
u.username = '张三';
u.password = '123';

const m = new MongoDb();
m.add(u);

命名空间

  • 命名空间和模块的区别

    命名空间:内部模块,主要用于组织代码,避免命名冲突。 模块:TS的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间。

namespace A {
export class Animal {
name: string | undefined;
age: number | undefined;
}
}
namespace B {
export class Animal {
name: string | undefined;
age: number | undefined;
}
}
const cat = new A.Animal()
const dog = new B.Animal()

TS装饰器

装饰器有什么用?

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来拓展类、属性、方法,参数的功能。

类装饰器

注意:类装饰器功能的实现需要在tsconfig.json文件中配置如下代码。

"experimentalDecorators": true
  1. 普通装饰器(无法传参)
function logClass(params: any) {
// 这里的params指的就是被装饰器下面的函数
console.log(params);
// 下面就是我们动态拓展的属性
params.prototype.apiUrl = 'http://www.baidu.com'
}

//
@logClass
class HttpClient {
constructor() {

}
getData() {

}
}

const h: any = new HttpClient();
console.log(h.apiUrl);
  1. 装饰器工厂(可以传参)
// 装饰器工厂
function logClass(params: any) {
// params:是装饰器传过来的参数
// 下面的target才是指的类本身
return function(target: any) {
console.log('这是target:',target);
console.log('这是params:',params);
target.prototype.apiUrl = params;
}
}

//
@logClass('666')
class HttpClient {
constructor() {

}
getData() {

}
}
const h: any = new HttpClient();
console.log(h.apiUrl); //666

类装饰器重载

function logClass(target: any) {
return class extends target {
apiUrl: string = '这个是修改后的url';
getData() {
this.apiUrl = '这个是修改后的url---'
console.log(this.apiUrl);

}
}
}
@logClass
class HttpClient {
apiUrl: string | undefined;
constructor() {
this.apiUrl = '这是构造函数中的URL'
}
getData() {
console.log(this.apiUrl);
}
}
const h = new HttpClient();
h.getData();

属性装饰器

属性装饰器表达式会在运行时当做函数被调用,传入下列两个参数

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名字。
// 属性装饰器
function logProperty(params: any) {
return function(target: any,attr: any) {
// 这里的target指的就是类的原型对象
// 这里的attr指的是类的属性
console.log(target);
console.log(attr);
target[attr] = params;
}
}
class HttpClient {
@logProperty('http://www.baidu.com')
url: string | undefined;
constructor() {

}
getData() {
console.log(this.url);
}
}
const h = new HttpClient();
h.getData()

方法装饰器

在方法装饰器中可以修改方法装饰器对应的方法或属性。

/**
* @description: 方法装饰器
* @param {any} params
* @return {*}
*/
function logFun(params: any) {
/**
* @description:
* @param {any} target:原型对象
* @param {any} methodName:方法名
* @param {any} desc:方法的属性描述
* @return {*}
*/
return function(target: any,methodName: any,desc: any) {
console.log(target);
console.log(methodName);
console.log(desc.value);

const oldMethod = desc.value;
desc.value = function(...args: any[]) {
args = args.map(item => {
return String(item)
})
oldMethod.apply(this,args)
}
}
}
class HttpClient {
url: string | undefined;
constructor() {
}
@logFun('你好')
getData(...args: any[]) {
console.log(args); // ['123','666']
console.log('这是getData中的方法');
}
}
const h = new HttpClient();
h.getData(123,'666')

方法参数装饰器

/**
* @description: 方法参数装饰器
* @param {any} params
* @return {*}
*/
function logParams(params: any) {
/**
* @description:
* @param {any} target:类的原型对象
* @param {any} methodName:参数对应的方法名
* @param {any} paramsIndex:参数对应的索引
* @return {*}
*/
return function(target: any,methodName: any,paramsIndex: any) {
console.log(params);
console.log(target);
console.log(methodName);
console.log(paramsIndex);
// 增加一个属性
target.apiUrl = params;
}
}
class HttpClient {
url: string | undefined;
constructor() {
}
getData(@logParams('你好') uuid: any) {
console.log(uuid);
}
}
const h: any = new HttpClient();
h.getData(123);
console.log(h.apiUrl); //你好

装饰器的执行顺序

首先看下面的代码

function logClass1(params: any) {
return function(target: any) {
console.log('类装饰器1');
}
}
function logClass2(params: any) {
return function(target: any) {
console.log('类装饰器2');
}
}
function logAttribute() {
return function(target: any,attr: any) {
console.log('属性装饰器');
}
}
function logMethod() {
return function(target: any,methodName: any,desc: any) {
console.log('方法装饰器');
}
}
function logParams1() {
return function (target: any,methodName: any,paramsIndex: any) {
console.log('方法参数装饰器1');
}
}
function logParams2() {
return function (target: any,methodName: any,paramsIndex: any) {
console.log('方法参数装饰器2');
}
}

@logClass1('111')
@logClass2('2222')
class HttpClient {
@logAttribute()
url: string | undefined;
constructor() {
}
@logMethod()
getData() {
return true
}
setDate(@logParams1() attr1: any,@logParams2() attr2: any) {
return true;
}
}

image.png

注意:在class内部执行顺序是按照代码顺序来的。


JustinTypeScript阅读需 11 分钟

类的注解方式

  1. 需要对实例的属性进行注解。
  2. 类的方法中有参数的需要进行注解。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}

let greeter = new Greeter("world");

继承中的super

1. 构造函数内部的super指的是父类的构造函数

image.png

2. 构造函数外部的super指的是父类本身

image.png

class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}

class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}

let sam = new Snake("Sammy the Python");

sam.move();

类成员的修饰符

1. public:公共的成员属性

  • 自身可以调用
  • 实例可以调用
  • 子类可以调用
class Animal {
public name: string;
public constructor(theName: string) { this.name = theName; }
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}

2. private : 只有自身可以调用

class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 错误: 'name' 是私有的.

3. protected: 自身可以调用,子类也可以调用,但是实例不可以调用

class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}

class Employee extends Person {
private department: string;

constructor(name: string, department: string) {
super(name)
this.department = department;
}

public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误

readonly修饰符

readobly关键字将属性设置为只读,这个属性必须在声明或者构造函数中被初始化。readonly不能对方法进行修饰。

class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.

参数属性

参数属性本质上就是一种简写的首发,就是将声明和赋值合并在一处。下面两种方式其实是等价的。

// 方式1
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}

// 方式2 class test { readonly numerOfLegs: number = 8; readonly name: string; constructor(Thename: string) { this.name = Thename; } }



JustinTypeScript阅读需 2 分钟

什么是TS中的类型推断?

以下面的例子为例,有时候我们并没有进行类型注解,TS经过推断后给我们添加的类型注解。 image.png

什么时候需要进行类型注解什么时候不需要呢?

  • 比如下面的代码,TS能够推断的,我们可以不进行注解
let a = 3;
  • 比如下面的代码,TS不能够对参数进行推断的情况下,我们需要进行注解
function test(a,b) {
return a + b;
}

什么是联合类型?

联合类型指的是一个变量可能具有多种类型,下面我们看一个简单的例子就明白了。

let a: string | number;

a = 2; a = '123';

* 联合类型调用共有属性可以,但是如果是非共有属性则不行。
```ts
function test(a: number | string) {
return a.split(''); //Error
}

function test(a: number | string) {
return a.toString() //Right
}

test(1)

JustinTypeScript阅读需 1 分钟

TS中的类型注解

  • 基础类型:boolean string number null undefined symbol any never
  • 对象:interface
  • 数组:number[] string[] boolean[]
  • 泛型的写法:Array\

TS带来的新的语法特性

  1. as 断言
  2. class(OOP面向对象的三大特性):封装、继承、多态 还有其他的,后续文章会进行详细的介绍。

创建tsconfig.json

tsc --init

修改tsc的输出路径

  1. 在tsconfig.json中对下面两行进行修改。 image.png

  2. 直接运行tsc指令,系统将直接将编译好的js文件输出到dist目录下。

原始数据的注解

  1. 布尔值的注解
let isDone: boolean = false;
  1. 数字类型的注解
let decLiteral: number = 6;
  1. 字符串类型的注解
let name2: string = "bob";
name2 = "smith";
  1. any类型的注解

    any类型可以表示任意类型,通过此类型的注解,不会有相应的代码提示,但是可以赋值为不同类型的数据。

let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

通过Object类型的注解可以赋值为任意类型,但是却只能调用真正的Object上的属性,也就是说只有你是真的对象才可以调用上面的方法。

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4; prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

>未给初始值的变量,初始值是any.
![image.png](https://img-blog.csdnimg.cn/img_convert/dc0dee707eb7c5c52ca47d35f4034fe2.png)

5. void类型的注解
>void类型的变量只能赋值为undefinednull,当一个函数没有返回值的时候,其注解类型为void.
```js
function warnUser(): void {
console.log("This is my warning message");
}
  1. undefined和null类型的注解
// Not much else we can assign to these variables!
let u: undefined = undefined;
let n: null = null;

在配置项中将"strictNullChecks"置为false的时候,undefined和null可以成为任何类型的子类型,所谓的子类型,就是说类型为number或其他的类型的值可以使undefined和null.

let a: number = undefined;
let b: number = null;

注意:在类型注解的时候,可以使用或运算符,同时注解多个类型

let a: string | boolean = true;
  1. never类型的注解

    返回never的函数必须存在无法达到的终点,never是任何类型的子类型,其他任何类型都不能赋值给never.

// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
  1. Object类型的注解

    使用Object类型的注解,可以很好的表示非原始类型,也就是除numberstringbooleansymbolnullundefined之外的类型。使用Object类型进行注解,可以很好的表示很多API。

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

引用类型的注解

  1. 数组类型的注解
// 方式1
let list: number[] = [1,2,3];

// 方式2
let list2: Array<number> = [4,5,6]
// 使用接口注解数组
interface list {
[index: number] : number | string
}
let temp: list = [1,2,3,'60']
// 注解类数组
interface Args {
[index: number]: any;
length: number;
callee: Function;
}

function test() {
let args: IArguments = arguments;
}

test()
  1. 函数的注解
  • 函数声明的注解方式
// 函数声明的注解方式:参数和返回值
function test(a: number,b: number): number {
return a + b;
}

test(1,2)
  • 函数表达式的注解方式
// 函数表达式的注解方式
let test2: (a: number, b: number) => number = function (a: number, b: number): number {
return a + b;
}
// 可以简写为下面的形式,也是较为常见的形式
let test: (a: number,b: number) => number = function (a,b) {
return a + b;
}
  • 可选参数和默认参数
// 可选参数
function test(a: number,b?: number): number {
return a;
}
// 默认参数
function test2(a: number,b = '666'): string {
return a + b;
}
  • 剩余参数
// 剩余参数
function test(a: number,b: number,...restOfName: string[]): number {
return a + b;
}
test(1,2,'3')
  • 参数的解构赋值
// 参数的解构赋值
function test({first,second}: {first: number,second: number}) {
return first + second;
}
test({first: 1,second: 2})

函数注解中的this指向问题


interface Card {
suits: string[];
cards: number[];
}

interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}

let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function() {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);

return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}

let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

重载

重载的意义在于告诉我们传入不同的参数,得到不同的结果。



## 类型断言
>类型断言类似于其他语言中的类型转换。

**尖括号语法**
```ts
let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

as语法

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

推荐使用as语法,因为如果你使用JSX的时候,只有as语法是被允许的。

欢迎大家关注我的专栏,一起学习TypeScript!


JustinTypeScript阅读需 5 分钟

TypeScript的五个特点

  1. TS是由微软开发的开源编程语言。
  2. TS是JS的超集。(所谓的超集是指兼容了所有的特性)
  3. TS是开发大型应用的基石。
  4. TS提供了更加丰富的语法提示。
  5. TS在编写阶段能够检查错误。

全局安装TS

npm install typescript -g

将TS文件编译为JS文件

tsc index.ts

为什么说TS是静态类型,JS是动态类型?

在JS中给一个字符串变量赋值为number是可以的,但是在TS中则不行,这可以理解为为什么说TS是静态的,JS是动态的。可以理解为TS中类型是一旦确定下来无法更改,JS则不是。

image.png


JustinTypeScript阅读需 1 分钟