TypeScript 安装使用及基础语法

TypeScript

下载

npm install -g typescript

查看

tsc -v

初始化 tsconfig.json

tsc --init

运行

tsc xx.ts 编译 xx.js
node xx.js

ts-node 可以直接运行 .ts 文件

npm install ts-node -g
ts-node xx.ts

基础类型

Boolean

let isDone: boolean = false;

Number

let decLiteral: number = 6;

let bigLiteral: bigint = 100n;

String

let name: string = "bob";

Array

第一种,可以在元素类型后面接上[],表示由此类型元素组成的一个数组
let list: number[] = [1, 2, 3];

也可以写复杂的数组类型

interface List {
  name: string;
}
const list: List[] = [{ name: "xr" }];

// 联合类型的数组
const list: (string | number)[] = [1, "2"];
第二种方式是使用数组泛型,Array<元素类型>
let list: Array<number> = [1, 2, 3];

Tuple

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

let x: [string, number] = ["xr", 18];

Enum

enum 类型是对 JavaScript 标准数据类型的一个补充。

enum Days {
    Sun=3,
    Mon,
    Tue,
    Wed
}
console.log(Days.Sun); // 默认为 0 如果写值 则从 值上面3开始

反向映射

console.log(Days[4]); // Mon
  • const 枚举
const enum Enum {
    A
}
  • 外部枚举

    外部枚举用来描述已经存在的枚举类型的形状。

declare enum Enum {
    A
}

Unknown

尽量使用 Unknown 替代 any

let notSure: unknown = 4;
notSure = "maybe a string instead";

Any

let notSure: any = 4;
notSure = "maybe a string instead";

Void

通常用在函数没有返回值情况

function warnUser(): void {
  console.log("This is my warning message");
}

Null 和 Undefined

let u: undefined = undefined;
let n: null = null;

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) {}
}

Object

object 表示非原始类型,也就是除 number,string,boolean,bigint,symbol,null 或 undefined 之外的类型。

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

类型断言

  • “尖括号”语法 jsx 语法不支持
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;

接口 interface

interface LabeledValue {
  label: string;
}

function printLabel(labeledObj: LabeledValue) {
  console.log(labeledObj.label);
}

let myObj = { label: "Size 101 Object" };
printLabel(myObj);

可选属性 ?

有些是只在某些条件下存在,或者根本不存在

interface LabeledValue {
  label: string;
  value?: string;
}
function printLabel(labeledObj: LabeledValue) {}
let myObj = { label: "Size 101 Object" };
let myObj2 = { label: "Size 101 Object", value: "value" };

只读属性 readonly

interface LabeledValue {
  readonly label: string;
}

function printLabel(labeledObj: LabeledValue) {
    // 无法分配到 "label" ,因为它是只读属性。ts(2540)
  labeledObj.label = "new label";
}

额外的属性检查 [propName: string]: any;

在接口中定义了某个属性 使用时超过这些属性直接写字面量方式会报错,写在变量中正常

interface LabeledValue {
  label: string;
}

function printLabel(labeledObj: LabeledValue) {}

// 这种写法可以
let myObj = { label: "Size 101 Object" };
printLabel(myObj);

// 这种写法报错
// 类型“{ label: string; value: string; }”的参数不能赋给类型“LabeledValue”的参数。对象文字可以只指定已知属性,并且“value”不在类型“LabeledValue”中。ts(2345)
printLabel({ label: "Size 101 Object", value: "value " });

接口改写

propName 可以任意变量
[propName: string] 表示以后添加的属性是 string 类型,属性值是 any 类型

interface LabeledValue {
  label: string;
  [propName: string]: any;
}

与函数一起使用

interface Func {
  (name: string, age: number): number;
}
var func: Func = function (name: string, age: number): number {
  return age;
};

在类中使用

interface ClockInterface {
  currentTime: Date;
  setTime(d: Date): void;
}

class Clock implements ClockInterface {
  currentTime: Date = new Date();
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h: number, m: number) {}
}

混合类型

interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function getCounter(): Counter {
  let counter = function(start: number) {} as Counter;
  counter.interval = 123;
  counter.reset = function() {};
  return counter;
}

接口继承

interface St extends Per {}

继承多个写法

interface St extends Per, Stu {}

接口合并

interface Per {
  name: string;
}

interface Per {
  age: number;
}
const per: Per = { name: "xr", age: 0 };

type 类型别名

type strType = string | number | boolean;
let strT: strType = 10;
strT = "11";

描述一个对象

type user = {
  name: string,
};

描述一个函数

type setuser = (name: string) => void;

限制字符串的选择

type strType3 = "男" | "女";
function getSex(sex: strType3) {
  return sex;
}
getSex("男");

在接口使用

interface Type {
  name: string;
}
interface Type2 {
  age: number;
}
type strType2 = Type | Type2;
// let strT2: strType2 = { name: 'zs', age: 33 }
let strT2: strType2 = { name: "zs" };
// let strT2: strType2 = { age: 33 };

实现继承

type User = {
  name: string,
};

type Per = User & {
  age: number,
};

const per: Per = { name: "xr", age: 20 };

联合类型、 类型保护、 交叉类型

联合类型

let type: string | number = 1;
type = "1";
interface Bird {
  fly();
  layEggs();
}

interface Fish {
  swim();
  layEggs();
}

declare function getSmallPet(): Fish | Bird;

let pet = getSmallPet();
pet.layEggs();
// 类型“Fish | Bird”上不存在属性“swim”。类型“Bird”上不存在属性“swim”。
pet.swim();

类型保护

  • 类型断言
(pet as Fish).swim();
  • 使用类型判定
    pet is Fish 就是类型谓词。 谓词为 parameterName is Type 这种形式,parameterName 必须是来自于当前函数签名里的一个参数名
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

if (isFish(pet)) {
  pet.swim();
}

else {
  pet.fly();
}
  • 使用 in 操作符
    对于 n in x 表达式,其中 n 是字符串字面量或字符串字面量类型且 x 是个联合类型
function move(pet: Fish | Bird) {
  if ("swim" in pet) {
    return pet.swim();
  }
  return pet.fly();
}
  • typeof 类型守卫
function padLeft(value: string, padding: string | number) {
  if (typeof padding === "number") {
    return Array(padding + 1).join(" ") + value;
  }
  if (typeof padding === "string") {
    return padding + value;
  }
  throw new Error(`Expected string or number, got '${padding}'.`);
}
  • instanceof 类型守卫

交叉类型

interface ErrorHandling {
  success: boolean;
  error?: { message: string };
}

interface ArtworksData {
  artworks: { title: string }[];
}

interface ArtistsData {
  artists: { name: string }[];
}

// 这些接口被组合后拥有一致的错误处理,和它们自己的数据

type ArtworksResponse = ArtworksData & ErrorHandling;
type ArtistsResponse = ArtistsData & ErrorHandling;

const handleArtistsResponse = (response: ArtistsResponse) => {
  if (response.error) {
    console.error(response.error.message);
    return;
  }

  console.log(response.artists);
};

函数类型

为函数定义类型

function add(x: number, y: number): number {
  return x + y;
}

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

书写完整函数类型

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

可选参数和默认参数

function buildName(firstName: string, lastName?: string) {
  if (lastName) return firstName + " " + lastName;
  else return firstName;
}
function buildName(firstName: string, lastName = "Smith") {
  return firstName + " " + lastName;
}

剩余参数

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

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

基本用法

class Demo {
  title = "默认值";
  constructor() {}
  say() {
    console.log(this.title);
  }
}

const demo = new Demo();
console.log(demo.title);

继承

class Demo {
  constructor(public title: string) {}
}

class De extends Demo {}

const demo = new De("自定义");
console.log(demo.title);

公共,私有与受保护的修饰符

public 默认值在类内,类外都可以访问
private 只能在类内部访问
protected 可以在类内部访问,也可以在继承中访问

class Demo {
  public title = "默认值";
  constructor(title: string) {
    this.title = title;
  }
}

const demo = new Demo("自定义");
console.log(demo.title);

属性的简写

class Demo {
  constructor(public title: string) {}
}

const demo = new Demo("自定义");
console.log(demo.title);
class Demo {
  constructor(
    public title: string,
    private age: number,
    protected sex: string
  ) {}
}

const demo = new Demo("自定义", 20, "男");
console.log(demo.title);

属性“age”为私有属性,只能在类“Demo”中访问。
console.log(demo.age);

属性“sex”受保护,只能在类“Demo”及其子类中访问。
console.log(demo.sex);


class De extends Demo {
  print() {
    // 属性“age”为私有属性,只能在类“Demo”中访问。
    console.log(this.age)
    console.log(this.sex,  this.title);
  }
}

readonly 修饰符,只读

你可以使用 readonly 关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。

class Demo {
  public readonly title = "默认值";
}

const demo = new Demo();
console.log(demo.title);
// 无法分配到 "title" ,因为它是只读属性。ts(2540)
demo.title = "出错了";

存取器 getters/setters

class Person {
  constructor(private _name: string) {}

  get name() {
    return this._name;
  }

  set name(val: string) {
    this._name = val;
  }
}
const per = new Person("xr");
console.log(per.name); // xr
per.name = "zs";
console.log(per.name); // zs

静态属性、方法

静态属性、方法只能类调用
静态方法中 this 指向类本身

class Demo {
  static type = 1;
  static say() {
    return this.type;
  }
}
console.log(Demo.type);

实现单例模式

class Person {
  // 存取实例对象
  private static instance: Person;
  // 使外部 不可以 `new Person`
  private constructor() {}
  // 添加类方法返回实例对象
  static getInstance() {
    // 静态方法中 `this` 指向类本身
    if (!this.instance) {
      this.instance = new Person();
    }
    return this.instance;
  }
}
const per = Person.getInstance();
const per2 = Person.getInstance();
console.log(per === per2); // true

抽象类 abstract

抽象类做为其它派生类的基类使用。

abstract class Department {

  constructor(public name: string) { }

  printName(): void {
    console.log('Department name: ' + this.name);
  }

  abstract printMeeting(): void; // 必须在派生类中实现
}

class AccountingDepartment extends Department {

  constructor() {
    super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
  }

  printMeeting(): void {
    console.log('The Accounting Department meets each Monday at 10am.');
  }

  generateReports(): void {
    console.log('Generating accounting reports...');
  }
}

let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在

泛型

函数定义

function identity<T>(arg: T): T {
  return arg;
}

使用
第一种是,传入所有的参数,包含类型参数

let output = identity < string > "myString"; // type of output will be 'string'

第二种方法更普遍。利用了类型推论

let output = identity("myString"); // type of output will be 'string'

interface 定义

interface Identity {
  <T>(arg: T): T;
}

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: Identity = identity;
let myIdentity2: <T>(arg: T) => T = identity;
interface Identity<T> {
  (arg: T): T;
}

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: Identity<string> = identity;

类中定义

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();

keyof 使用

interface Person {
  name: string;
  age: number;
  gender: string;
}

class Teacher {
  constructor(public info: Person) {}
  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key];
  }
}

const teacher = new Teacher({
  name: "xr",
  age: 20,
  gender: "男",
});
console.log(teacher.getInfo("gender"));

命名空间

同一文件下

Demo.ts

namespace Demo {
  export interface IDemo {
    name: string;
  }
}

const demo: Demo.IDemo = {
  name: "demo",
};

Demo 是全局变量可以直接使用
要使用 Demo 下的 IDemo 接口就必须导出

其他文件使用

Demo.ts

export namespace Demo {
    export interface IDemo{
        name: string;
    }
}

xx.vue

import { Demo } from "./ts/demo";
const person: Demo.IDemo = { name: "xr" };

不必要的命名空间
再次重申,不应该对模块使用命名空间,使用命名空间是为了提供逻辑分组和避免命名冲突。

  • 上面代码改进

demo.ts

export interface IDemo {
  name: string;
}

xx.vue

import { IDemo } from "./ts/demo";
const person: IDemo = { name: "xr" };

声明文件

外部模块

xx.d.ts

declare module "url" {
  export interface Url {
    protocol?: string;
    hostname?: string;
    pathname?: string;
  }
  export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
}

declare module "path" {
  export function normalize(p: string): string;
  export function join(...paths: any[]): string;
  export let sep: string;
}

/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");
  • 外部模块简写
    假如你不想在使用一个新模块之前花时间去编写声明,你可以采用声明的简写形式以便能够快速使用它
    xx.d.ts
declare module "hot-new-module";

简写模块里所有导出的类型将是 any。

import x, { y } from "hot-new-module";
x(y);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值