TypeScript 基本数据类型实例详解

目录
  • TypeScript 介绍
  • 类型分配
  • 类型推导
  • 数组
  • 元组
  • object
  • null 和 undefined
  • 特殊类型
    • any
    • unknown
    • never
    • void

TypeScript 介绍

  • TypeScript 是 JavaScript 的超集,提供了 JavaScript 的所有功能,并提供了可选的静态类型、Mixin、类、接口和泛型等特性。
  • TypeScript 的目标是通过其类型系统帮助及早发现错误并提高 JavaScript 开发效率。
  • 通过 TypeScript 编译器或 Babel 转码器转译为 JavaScript 代码,可运行在任何浏览器,任何操作系统。
  • 任何现有的 JavaScript 程序都可以运行在 TypeScript 环境中,并只对其中的 TypeScript 代码进行编译。
  • 在完整保留 JavaScript 运行时行为的基础上,通过引入静态类型定义来提高代码的可维护性,减少可能出现的 bug。
  • 永远不会改变 JavaScript 代码的运行时行为,例如数字除以零等于 Infinity。这意味着,如果将代码从 JavaScript 迁移到 TypeScript ,即使 TypeScript 认为代码有类型错误,也可以保证以相同的方式运行。
  • 对 JavaScript 类型进行了扩展,增加了例如 anyunknownnevervoid
  • 一旦 TypeScript 的编译器完成了检查代码的工作,它就会 擦除 类型以生成最终的“已编译”代码。这意味着一旦代码被编译,生成的普通 JS 代码便没有类型信息。这也意味着 TypeScript 绝不会根据它推断的类型更改程序的 行为。最重要的是,尽管您可能会在编译过程中看到类型错误,但类型系统自身与程序如何运行无关。
  • 在较大型的项目中,可以在单独的文件 tsconfig.json 中声明 TypeScript 编译器的配置,并细化地调整其工作方式、严格程度、以及将编译后的文件存储在何处。

类型分配

创建变量时,TypeScript 有两种分配类型的方式:

  • 显式的 - 明确写出类型。更易于阅读且更有目的性。
  • 隐式的 - 不写出类型,TypeScript 将根据分配的值“猜测”类型(称为 infer 类型推导)。分配更短,输入速度更快,并且经常在开发和测试时使用。
let firstName = "Dylan"; // 推断为 string 类型
firstName = 33; // 现在赋值为 number 类型,报错

TypeScript 不能正确地推断出变量的类型时,将设置类型为 any(禁用类型检查的类型)。

// json 为隐式 any 类型,因为 JSON.parse 不知道它返回什么类型的数据
let json = JSON.parse("55");
console.log(typeof json); // number
json = '1';
console.log(typeof json); // string

类型推导

  • 在没有显式类型注释时使用类型推断来提供类型信息。例如,下面隐式声明变量:
let x = 3;

变量的类型 x 将被推断为 number,这种推断发生在初始化变量和成员、设置参数默认值和确定函数返回类型时。

  • 当从多个表达式进行类型推断时,这些表达式的类型用于计算“最佳通用类型”。
let x = [0, 1, ''];

要推断上例中 x 的类型,我们必须考虑每个数组元素的类型。在这里,我们为数组类型提供了两种选择:numberstring,可以看到提示推导为 let x: (number | string)[]

  • 在某些情况下类型共享公共结构,但没有一种类型是所有候选类型的超类型。
class Animal {}
class Rhino extends Animal {
  hasHorn: true;
}
class Elephant extends Animal {
  hasTrunk: true;
}
class Snake extends Animal {
  hasLegs: false;
}
let zoo = [new Rhino(), new Elephant(), new Snake()];

当没有找到“最佳通用类型”时,得到的推断将是联合数组类型,可以看到提示推导为 let zoo: (Rhino | Elephant | Snake)[]

理想情况下,我们可能希望 zoo 被推断为 Animal[],但是因为数组中没有严格意义上的 Animal 类型的对象,所以我们没有对数组元素类型进行推断。为了纠正这一点,当没有一个类型是所有其他候选类型的超级类型时,就明确地提供类型。

let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
  • 当表达式的类型由其所在位置暗示时,就会出现上下文类型化。例如:
window.onmousedown = function (mouseEvent) {
  console.log(mouseEvent.button);
  console.log(mouseEvent.kangaroo);
};

在这里,TypeScript 类型检查器通过 Window.onmousedown 事件能够推断出 mouseEvent 参数的类型,该参数确实包含 button 属性,但不包含 kangaroo 属性。可以看到报错提示:Property 'kangaroo' does not exist on type 'MouseEvent'.。TypeScript 足够聪明,它也可以在其他上下文中推断类型:

window.onscroll = function (uiEvent) {
  console.log(uiEvent.button);
};

TypeScript 知道 Window.onscroll 事件中参数 uiEvent 是一个 UIEvent,而不是像前面示例那样的 MouseEventUIEvent 对象不包含 button 属性,因此会抛出错误 Property 'button' does not exist on type 'Event'.

如果此函数不在上下文类型位置,则函数的参数将隐式具有类型 any,并且不会发出错误(除非使用 noImplicitAny 配置):

// @noImplicitAny: false
const handler = function (uiEvent) {
  console.log(uiEvent.button); // <- OK
};

我们还可以显式地为函数的参数提供类型信息以覆盖任何上下文类型:

window.onscroll = function (uiEvent: any) {
  console.log(uiEvent.button); // 不报错,打印undefined,因为UIEvent对象不包含button属性
};

上下文类型化适用于许多情况。常见情况包括函数调用的参数、赋值的右侧、类型断言、对象和数组文字的成员以及返回语句。上下文类型也会充当“最佳通用类型”中的候选类型。例如:

function createZoo(): Animal[] {
  return [new Rhino(), new Elephant(), new Snake()];
}

在此示例中,“最佳通用类型”将从以下四个类型中选择:AnimalRhinoElephantSnake。最终,通过“最佳通用类型”算法为 Animal

数组

TypeScript 具有定义数组的特定语法。

  • 在元素类型后面加上 []
const arr: number[] = [1, 2];
  • 使用数组泛型。
const arr2: Array<number> = [1, 2];
  • readonly 关键字可以防止数组内容被更改。
const arr: readonly number[] = [1, 2];
// arr.push(3); // Property 'push' does not exist on type 'readonly number[]'.
  • 如果数组有值,TypeScript 可以推断它的类型。
const numbers = [1, 2, 3]; // 推断为类型 number[]
numbers.push(4); // OK
// numbers.push("2"); // Argument of type 'string' is not assignable to parameter of type 'number'

元组

数组中元素的数据类型都一般是相同的(any[] 类型的数组可以不同),如果存储的元素数据类型不同,则需要使用元组。

  • 如果添加未定义的类型,会抛出错误;如果赋值时类型相同,顺序不同,同样会抛出错误。
let x: [string, number];
x = ['hi', 1];
// x.push(true); // Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
// x = [1, 'hi']; // Type 'number' is not assignable to type 'string'. Type 'string' is not assignable to type 'number'.
  • readonly 关键字可以防止元组内容被更改。
let y: readonly [string, number] = ['hi', 1];
// y.push(undefined); // Property 'push' does not exist on type 'readonly [string, number]'.
  • “命名元组”允许为我们的索引值所代表的内容提供更多上下文。
const graph: [x: number, y: number] = [55.2, 41.3];
const [a, b] = graph;

object

  • TypeScript 具有定义对象的特定语法。
const car: { type: string, model: string, year: number } = {
  type: "Toyota",
  model: "Corolla",
  year: 2009
};

对象类型可以单独写,也可以作为类型别名和接口重用。

  • TypeScript 可以根据属性的值推断属性的类型。
const car = {
  type: "Toyota",
};
car.type = "Ford";
// car.type = 2; // Type 'number' is not assignable to type 'string'.
  • 可选属性是不必在对象定义中定义的属性。
const car: { type: string, mileage?: number } = { // no error
  type: "Toyota"
};
car.mileage = 2000;
  • 索引签名可用于没有定义属性列表的对象。
const nameAgeMap: { [index: string]: number } = {};
nameAgeMap.Jack = 25; // no error
nameAgeMap.Mark = "Fifty"; // Error: Type 'string' is not assignable to type 'number'.

上述索引签名也可以通过使用工具类型 Record<string, number> 实现。

  • Typescript 中的对象必须是特定类型的实例。
const sites = {
  site1: "Runoob",
  site2: "Google",
};
sites.sayHello = function() {
  console.log("hello " + sites.site1);
};
sites.sayHello();

上面示例在对象上面没有对应的 sayHello 类型定义,将不能进行属性赋值,会出现编译错误,:Property 'sayHello' does not exist on type '{ site1: string; site2: string; }'.,所以必须在对象上面定义类型模板。

const sites = {
  site1: "Runoob",
  site2: "Google",
  sayHello: function() {}
};

null 和 undefined

默认情况下 nullundefined 处理是禁用的,可以通过在 tsconfig.json 中设置 strictNullCheckstrue 来启用。

  • nullundefined 是原始类型,可以像字符串等其他类型一样使用。
let y: undefined = undefined;
console.log(typeof y);
let z: null = null;
console.log(typeof z);
  • 可选链 ?. 是一种原生 JavaScript 特性,可以很好地与 TypeScript 中的 nullundefined 配合使用。
interface House {
  sqft: number;
  yard?: {
    sqft: number;
  };
}
function printYardSize(house: House) {
  const yardSize = house.yard?.sqft;
  if (yardSize === undefined) {
    console.log('No yard');
  } else {
    console.log(`Yard is ${yardSize} sqft`);
  }
}
let home: House = {
  sqft: 500
};
printYardSize(home); // 'No yard'
  • 空值合并 ?? 是另一个 JavaScript 特性,它也可以很好地与 TypeScript 的空值处理配合使用。
function printMileage(mileage: number | null | undefined) {
  console.log(`Mileage: ${mileage ?? 'Not Available'}`);
}
printMileage(null); // 'Mileage: Not Available'
printMileage(0); // 'Mileage: 0'
  • TypeScript 还有一种特殊的空值断言语法,可以在不进行任何显式检查的情况下从类型中删除 nullundefined。在任何表达式之后写 !,表明该值不是 nullundefined
function liveDangerously(x?: number | null) {
  // No error
  console.log(x!.toFixed());
}

就像其他类型断言一样,这不会改变代码的运行时行为,所以只有当您知道该值不能为 nullundefined 时使用 !

  • 即使启用了 strictNullChecks,默认情况下 TypeScript 也会假定数组访问永远不会返回 undefined(除非 undefined 是数组类型的一部分)。通过配置 noUncheckedIndexedAccess 可用于更改此行为。
let array: number[] = [1, 2, 3];
let value = array[0]; // `number | undefined` "noUncheckedIndexedAccess": true

特殊类型

TypeScript 具有可能不引用任何特定类型数据的特殊类型。

any

any 是一种禁用类型检查并有效地允许使用所有类型的类型。any 类型是一种消除错误的有用方法,因为它禁用了类型检查,但 TypeScript 将无法提供类型安全,并且依赖类型数据的工具(例如自动完成)将无法工作。所以,我们应尽量避免使用它。

以下三种情况可以使用 any 类型。

  • 变量的值会动态改变时,比如来自用户的输入。
let x: any = 1; // 数字类型
x = 'I am who I am'; // 字符串类型
x = false; // 布尔类型
  • 改写现有代码时,任意值允许在编译时可选择地包含或移除类型检查。
let v: any = true;
v = "string"; // 没有错误
v.ifItExists(); // ifItExists 方法在运行时可能不存在而报错,但这里并不会检查
console.log(Math.round(v)); // 没有错误
  • 定义存储各种类型数据的数组。
const arrayList: any[] = [1, false, 'fine'];
arrayList[1] = 100;

unknown

unknown 类型表示任何值,类似于 any 类型,但更安全,因为用未知值做任何事情都是不合法的。由于 any 违背了类型检查的初衷,一般不建议使用,尤其在有了 unknown 类型之后。

  • 任何类型可以分配给 anyunknownany 可以分配给任何类型,unknown 只能分配给 unknown 或者 any
let a: any;
let n: number;
let w: unknown = 1;
w = "string";
w = a;
a = w;
n = a;
// n = w; // Type 'unknown' is not assignable to type 'number'
  • 函数返回值类型为 unknown 时要有 return 语句。
function f(): unknown {} // A function whose declared type is neither 'void' nor 'any' must return a value
  • 当不知道输入的数据类型时,最好使用 unknown。要稍后添加类型,需要强制转换它。
const w = {
  runANonExistentMethod: () => {
    console.log("I think therefore I am");
  }
} as { runANonExistentMethod: () => void };
if(typeof w === 'object' && w !== null) {
  (w as { runANonExistentMethod: Function }).runANonExistentMethod();
}

never

never 代表从不会出现的值,在函数中它通常表现为抛出异常或无法执行到终止点(例如无限循环)。never 很少单独使用,它的主要用途是在高级泛型中。

function error(message: string): never {
  throw new Error(message);
}
function loop(): never {
  while (true) {}
}

void

表示函数没有任何返回语句,或者不从这些返回语句返回任何显式值。在 JavaScript 中,不返回任何值的函数将隐式返回值 undefined。但是,void 和返回 undefined 在 TypeScript 中不是一回事。

function hello(): void {
  console.log("Hello");
  return true; // Type 'boolean' is not assignable to type 'void'.
}
hello();

函数类型 type vf = () => void 在实现时可以返回任何其他值,以下类型的实现是有效的:

type voidFunc = () => void;
const f1: voidFunc = () => {
  return true;
};
const f2: voidFunc = () => true;
const f3: voidFunc = function() {
  return true;
};
const v1 = f1();
const v2 = f2();
const v3 = f3();
console.log(v1, v2, v3); // true true true

以上就是TypeScript 基本数据类型实例详解的详细内容,更多关于TypeScript 基本数据类型的资料请关注我们其它相关文章!

(0)

相关推荐

  • TypeScript 类型级别示例介绍

    介绍 这是一门在线课程,旨在将您的TypeScript技能从中级提升到高级.它将使你深入了解类型系统的基本原理,并指导你完成其高级功能.在这里,你会找到成为TypeScript专家所需的一切-不仅有深入的内容,还有练习新技能的有趣挑战,就像这里的这个. /** * Try assigning "World" to `type Hello`! */ type Hello = "..."; // Type-level unit tests! // If the next

  • TypeScript 背后的结构化类型系统原理详解

    目录 前言 什么是结构化类型系统? 什么是标称类型系统? 结构化类型系统等价于鸭子类型系统吗? 如何在 TypeScript 中模拟标称类型系统? 交叉类型实现 类实现 总结 前言 你能说清楚类型.类型系统.类型检查这三个的区别吗?在理解TypeScript的结构化类型系统之前,我们首先要搞清楚这三个概念和它们之间的关系 类型:即对变量的访问限制与赋值限制.如 TypeScript 中的原始类型.对象类型.函数类型和字面量类型等类型,当一个变量类型确定后,你不能访问这个类型中不存在的属性或方法,

  • TypeScript类型级别和值级别示例详解

    目录 对值级别编程类型级别编程区分 类型级编程 挑战是如何工作的 挑战 对值级别编程类型级别编程区分 首先,让我们对值级别编程和类型级别编程进行重要区分. 值级别编程让我们编写将在生产中运行的代码即运行期,并为我们的用户提供有用的东西. 类型级别编程帮助我们确保代码在发布之前即编译期不包含错误,在运行期会被完全删除 JavaScript没有类型,所以所有JavaScript都是值级别的代码: // A simple Javascript function: function sum(a, b)

  • typescript基本数据类型HTMLElement与Element区别

    目录 TypeScript是什么? TypeScript的安装和编译 上手实践 typescript中HTMLElement 和 Element的区别 探讨 TypeScript是什么? 涉及代码仓库 github.com/Dartgm/dart… TypeScript是由微软开发的一款开源的编程工具 TypeScript是JavaScript的超集,遵循最新的ES5/ES6规范,TypeScript扩展了JavaScript的语法 TypeScript更像后端Java,C#这样的面向对象的语言

  • 简单三行代码函数实现几十行Typescript类型推导

    目录 场景 摸鱼吃瓜式排查 元组大法 感叹 场景 最近在设计一些基础的项目框架设计上的 sdk api,比如埋点系统.权限系统之类的,要提供一些便捷的封装方法给上层使用.于是遇到了这么个场景. 有一个对象常量里,存了一些方法,例如: const METHODS = { a: () => "a" as const, b: () => "b" as const, c: () => "c" as const } 然后想要封装这样一个

  • TypeScript 基本数据类型实例详解

    目录 TypeScript 介绍 类型分配 类型推导 数组 元组 object null 和 undefined 特殊类型 any unknown never void TypeScript 介绍 TypeScript 是 JavaScript 的超集,提供了 JavaScript 的所有功能,并提供了可选的静态类型.Mixin.类.接口和泛型等特性. TypeScript 的目标是通过其类型系统帮助及早发现错误并提高 JavaScript 开发效率. 通过 TypeScript 编译器或 Ba

  • MySQL数据类型中DECIMAL的用法实例详解

    MySQL数据类型中DECIMAL的用法实例详解 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法. 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数.如果在一个FLOAT(8, 1)的列中存储1. 2 3 4 5 6,则结果为1. 2.如果将相同的值存入FLOAT(8, 4) 的列中,则结果为1. 2 3 4 6. 这表示应该定义具有足够位数的浮点列以便

  • 判断js数据类型的函数实例详解

    function judgeType(change) { if (arguments.length == 0) { return '0';//无参数传入 } if (change === null) { return 'null' } if (change === undefined && arguments.length > 0) { return 'undefined' } if (change instanceof Function) { return 'function' }

  • Python数据类型之列表和元组的方法实例详解

    引言 我们前面的文章介绍了数字和字符串,比如我计算今天一天的开销花了多少钱我可以用数字来表示,如果是整形用 int ,如果是小数用 float ,如果你想记录某件东西花了多少钱,应该使用 str 字符串型,如果你想记录表示所有开销的物品名称,你应该用什么表示呢? 可能有人会想到我可以用一个较长的字符串表示,把所有开销物品名称写进去,但是问题来了,如果你发现你记录错误了,想删除掉某件物品的名称,那你是不是要在这个长字符串中去查找到,然后删除,这样虽然可行,那是不是比较麻烦呢. 这种情况下,你是不是

  • TypeScript顺时针打印矩阵实现实例详解

    目录 前言 梳理思路 实现代码 示例代码 前言 有一个矩阵,如何按照从外向里以顺时针的顺序依次打印出每一个元素?本文将跟大家分享下这个算法,欢迎各位感兴趣的开发者阅读本文. 梳理思路 当我们遇到一个复杂的问题时,可以通过举例将它画出来,这样就可以更直观的发现规律.那么我们就先构造一个矩阵出来,如下所示: const matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ]; 顺时针访问一个矩阵,那么它的访

  • 前端算法之TypeScript包含min函数的栈实例详解

    目录 前言 思路梳理 实现代码 示例代码 前言 基于数据结构: “栈”,实现一个min函数,调用此函数即可获取栈中的最小元素.在该栈中,调用min.push.pop的时间复杂度都是O(1). 本文就跟大家分享下这个算法,欢迎各位感兴趣的开发者阅读本文. 思路梳理 相信大多数开发者看到这个问题,第一反应可能是每次往栈中压入一个新元素时,将栈里的所有元素排序,让最小的元素位于栈顶,这样就能在O(1)的时间内得到最小元素了.但这种思路不能保证最后入栈的元素能够最先出栈,因此这个思路行不通. 紧接着,我

  • python之sqlalchemy创建表的实例详解

    python之sqlalchemy创建表的实例详解 通过sqlalchemy创建表需要三要素:引擎,基类,元素 from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String 引擎:也就是实体数据库连接 engine = create_engine('mysql+pymysql://go

  • java操作mongoDB查询的实例详解

    java操作mongo查询的实例详解 前言: MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型.Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且

  • Angular.js之作用域scope'@','=','&'实例详解

    什么是scope AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执行环境.作用域有层次结构,这个层次和相应的 DOM 几乎是一样的.作用域能监控表达式和传递事件. 在 HTML 代码中,一旦一个 ng-app 指令被定义,那么一个作用域就产生了,由 ng-app 所生成的作用域比较特殊,它是一个根作用域($rootScope),它是其他所有$Scope 的最顶层. 除了用 ng-app 指令可以产生一个作用域之外,其他的指令如 ng-controller,ng-repeat

  • MySQL操作之JSON数据类型操作详解

    上一篇文章我们介绍了mysql数据存储过程参数实例详解,今天我们看看MySQL操作之JSON数据类型的相关内容. 概述 mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点.但mysql毕竟是关系型数据库,在处理json这种非结构化的数据时,还是比较别扭的. 创建一个JSON字段的表 首先先创建一个表,这个表包含一个json格式的字段: CREATE TABLE table_name ( id INT NOT NULL

随机推荐