ts学习总结系列-part1

139 阅读5分钟

原始数据类型

  • string
  • number
  • boolean

数组表示方式

  • 数组 [1,2,3] 可以用 number[] 或 Array 来表示它的类型

any

  • any 如果某个变量是any类型,可以用任何类型的值赋值给它,这可以避免大部分类型检查错误
  • noImplicitAny 如果我们没有给某个变量声明具体某个类型,则typescript 会默认分配any类型,这就失去了类型检测的意义,我们可以用 noImplicitAny true来避免

类型自动推断

  • 我们可以显式的声明变量类型,或者ts也会自动帮我们推断
let myName: string = "Alice";

// 自动推断为string类型,可以不需要显式声明
let myName = "Alice";

函数

  • 函数是在JavaScript中传递数据的主要方法。TypeScript允许您指定函数的输入值和输出值的类型
  • 参数类型声明
// Parameter type annotation
function greet(name: string) {
  console.log("Hello, " + name.toUpperCase() + "!!");
}

greet(42)
// 如果我们传入参数类型不对,则会有以下提示

Argument of type 'number' is not assignable to parameter of type 'string'.

即使你不声明参数name的类型为string,ts也会检查你实际传入参数的数量

  • 返回值类型声明
function getFavoriteNumber(): number {
 return 26;
}

返回值类型也可以像参数一样不显示声明,ts会根据return 区块来推断类型

匿名函数

  • 匿名函数可根据上下文推测类型,如以下根据names数组的字符串类型推测到toUppercase方法拼写错误,应为toUpperCase
// No type annotations here, but TypeScript can spot the bug
const names = ["Alice", "Bob", "Eve"];

// Contextual typing for function
names.forEach(function (s) {
  console.log(s.toUppercase());

Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?

对象类型

  • 对象几乎包含任何类型的属性值
// 参数是对象类型
function printCoord(pt: { x: number; y: number }) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 3, y: 7 });

参数是{ x: number; y: number },属性可以用,;分割;如果对象中的属性没有类型,则默认为any类型

  • 可选的对象类型,用?表示
function printName(obj: { first: string; last?: string }) {
  // ...
}
// Both OK
printName({ first: "Bob" });
printName({ first: "Alice", last: "Alisson" });
  • ? 最佳实践方式
function printName(obj: { first: string; last?: string }) {
 // Error - might crash if 'obj.last' wasn't provided!
 console.log(obj.last.toUpperCase());
// Object is possibly 'undefined'.
// 方式1:
 if (obj.last !== undefined) {
   // OK
   console.log(obj.last.toUpperCase());
 }

 // A safe alternative using modern JavaScript syntax:
 // 方式2(推荐)
 console.log(obj.last?.toUpperCase());
}

联合类型

  • 基于现有的类型结合操作符可以定义成联合类型
  • 例子
function printId(id: number | string) {
 console.log("Your ID is: " + id);
}
// OK
printId(101);
// OK
printId("202");
// Error
printId({ myID: 22342 });

number | string 为联合类型

  • 通过if分支去判断联合类型
function printId(id: number | string) {
  if (typeof id === "string") {
    // In this branch, id is of type 'string'
    console.log(id.toUpperCase());
  } else {
    // Here, id is of type 'number'
    console.log(id);
  }
}

类型别名

  • 我们可以抽取出重复使用的类型,用type 来定义
type Point = {
  x: number;
  y: number;
};

// Exactly the same as the earlier example
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}

printCoord({ x: 100, y: 100 });

interface

interface Point {
  x: number;
  y: number;
}

function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}

printCoord({ x: 100, y: 100 });

type vs interface

  1. interface 可以extend ,type 可以通过& 扩展新属性
// Extending an interface

interface Animal {
  name: string
}

interface Bear extends Animal {
  honey: boolean
}

const bear = getBear() 
bear.name
bear.honey

// Extending a type via intersections

type Animal = {
  name: string
}

type Bear = Animal & { 
  honey: Boolean 
}

const bear = getBear();
bear.name;
bear.honey;
  1. interface可以往已经存在的接口声明上添加新属性,type 会报错
// Adding new fields to an existing interface

interface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});

// A type cannot be changed after being created

type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

 // Error: Duplicate identifier 'Window'.

类型推断 as

  • 有时候ts不知道我们值的类型,会提示错误,我们可以利用 as来告诉它某个确定的类型

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
// 或
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

  • 强制类型转换
// 以下是不被允许的
const x = "hello" as number;

可以先把值类型转换为 unknow 或者 any 类型

const a = (expr as any) as T;

字面量类型

  • 不同于string 或者 number 类型,字面量类型具体到某个值
let x: "hello" = "hello";
// OK
x = "hello";
// not ok ,Type '"howdy"' is not assignable to type '"hello"'.
x = "howdy";
  • 字面量在联合类型中用途比较广泛
// 1.函数参数是字面量联合类型
function printText(s: string, alignment: "left" | "right" | "center") {
  // ...
}
// 2.函数的返回值是字面量联合类型
function compare(a: string, b: string): -1 | 0 | 1 {
  return a === b ? 0 : a > b ? 1 : -1;
}
  • 字面量类型也可以与非字面量类型结合成为联合类型
interface Options {
  width: number;
}
function configure(x: Options | "auto") {
  // ...
}

字面量推断

  • 当我们初始化一个对象时,obj.counter 为number类型
const obj = { counter: 0 };
// 同理
// 以下会报错,string类型的method传递给具体的类型GEt | POST类型时
declare function handleRequest(url: string, method: "GET" | "POST"): void;

const req = { url: "https://example.com", method: "GET" };
// req {
    url:string,
    method:string
}
handleRequest(req.url, req.method);

有两种方案可以解决以上问题

1. as 类型断言
// Change 1:
const req = { url: "https://example.com", method: "GET" as "GET" };
// Change 2
handleRequest(req.url, req.method as "GET");
2. as const
// change1
const req = { url: "https://example.com", method: "GET" } as const;
// change2
const req = <const>{ url: "https://example.com", method: "GET" } 
handleRequest(req.url, req.method);

const 此时作用主要是对象中的属性类型变为只读且属性类型为具体的字面量类型

strictNullChecks

  • 如果 strictNullChecks on 的话,值为null或者undefiend的情况要考虑到
function doSomething(x: string | null) {
 if (x === null) {
   // do nothing
 } else {
   console.log("Hello, " + x.toUpperCase());
 }
}

null 断言操作符 !

  • 在表达式添加后缀 !可以确保值不为 undefiend 或者 null
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}

参考链接: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html