【TypeScript】类型声明及应用(二)

【TypeScript】类型声明及应用(二)



在这里插入图片描述

一、前言

TypeScript开发中需要对定义的变量指定类型,目前版本都支持哪些类型,每一个类型都有哪些含义,在这篇文章中,我们将会对其进行总结说明

二、JavaScript基本数据类型以及TypeScript特有的数据类型。
  • JavaScript基本数据类型: String、Number、null、undefined、Boolean、Symbol
  • TypeScript数据类型:任意类型(any)、元组类型(tuple)、枚举类型(enum)、void类型、never类型、unknown类型、类型断言(Type Assertion)、接口类型(interface)、函数类型(Function)

具体分别含义如下

2.1 JavaScript(JS)基本数据类型包括:
  • 数字(Number):表示整数和浮点数,如 1、-2、3.14 等。
  • 字符串(String):表示文本数据,用单引号(')或双引号(")括起来,如 ‘hello’、“world” 等。
  • 布尔值(Boolean):表示真或假,只有两个值,true 和 false。
  • null:表示空值,即没有任何值的变量。
  • undefined:表示未定义,即变量声明了但没有赋值。
  • Symbol:表示唯一的标识符,通常用于对象属性的键名。

注意,JS 还有一种复杂数据类型,即对象(Object),它可以包含多个属性,每个属性是一个键值对。对象的属性可以是基本数据类型或其他对象,甚至可以是函数。

2.2 TypeScript 特有的数据类型包括:
  • 任意类型(any):表示可以是任何类型。
  • 元组类型(tuple):表示有限数量的未知类型元素的数组。
  • 枚举类型(enum):表示具有命名值的一组相关的常量。
  • void类型:表示没有任何类型,常用于函数的返回值类型。
  • never类型:表示永远不存在的值的类型。
  • unknown类型:表示任何类型的值,但在使用前必须先进行类型检查。
  • 类型断言(Type Assertion):表示在某些情况下需要手动告诉编译器变量的类型。
  • 接口类型(interface):表示对象的类型。
  • 函数类型(Function):表示函数的类型。
三、类型使用实践
3.1 基础类型的声明和使用

String、Number、null、undefined、Boolean、Symbol基础类型的声明和使用
基础类型在JavaScript中的常规写法如下:

 let name = "suwu150";
 let count = 1111;
 let score = null;
 let address = undefined;
 let isShow = false;
 const nameShow = Symbol("foo");

同样的,我们也简单认识下TypeScript中的写法如下:

 let name: string = "suwu150";
 let count: number = 1111;
 let score: null = null;
 let address: undefined = undefined;
 let isShow: boolean = false;
 const nameShow: unique symbol = Symbol("foo");

使用在线演练场或者本地编辑器进行编译后,我们能看到以下的结果:


"use strict";
var name = "suwu150";
var count = 1111;
var score = null;
var address = undefined;
var isShow = false;
var nameShow = Symbol("foo");


注意,这个结果是在官方在线演练场中编译后的结果,有些老铁可能会在本地终端使用tsc进行验证,会发现运行结果和我这个不一致,这是因为 tsconfig.json中配置compilerOptions参数,如下,当然还有很多其他的配置,具体可以查找资料:

{
    
    
  "compilerOptions": {
    
    
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "ES2022",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": [
      "es2015.promise",
      "dom",
      "es5",
    ],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  }
}

在体验了正常定义之后,我们体验下,定义的类型和赋值类型有所差异的情况下,会有如下提示, 继续编写TypeScript代码

 let myName: string = "suwu150";
 let count: number = 1111;
 let score: null = null;
 myName = 2023;
 count = '平平安安'
 score = 888

继续编译看结果
在这里插入图片描述

3.2 任意类型(any)

在 TypeScript 中,可以使用any类型来表示任意类型。
any类型可以接受任何类型的值,而且不会进行类型检查。例如:

let value: any = "hello";
value = 123;
value = true;

在上面的示例中,变量value的类型为any,因此可以被赋值为字符串、数字或布尔值。

尽管any类型非常灵活,但是过度使用它可能会导致代码难以维护和理解。在实际开发中,应该尽可能地使用更具体的类型来避免类型错误。

3.3 元组类型(tuple)

TypeScript中的元组类型(tuple)是一种特殊的数组类型,它允许开发人员在定义数组时指定每个元素的类型和数量,并且这些类型和数量必须与定义时一致,否则会引发类型错误。

元组类型的语法如下:


let myTuple: [string, number];
myTuple = ['name', 23023]

在这里插入图片描述
对于TypeScript中有多种形式的元祖书写方式。

(1)使用方括号和逗号表示元组类型

let tuple: [string, number] = ["hello", 123];

(2)使用数组多元素类型表示元组类型:
	
let tuple: Array<string | number> = ["hello", 123];

(3)使用类型别名表示元组类型:
type Tuple = [string, number];
let tuple: Tuple = ["hello", 123];

需要注意的是,上述方式一、方式三其实是对元祖长度的一个限制。也就是不能超过指定定义的长度,否则编译时会报错误提示。


let tuple: [string, number] = ["hello", 123, 4444];  // error
let tuple2: Array<string | number> = ["hello", 123, "hello", 123, 4444];

3.4 枚举类型(enum)

TypeScript 的枚举类型(enum)是一种具有有限数量的命名常量值的数据类型。

枚举类型可以使代码更易于维护和更新,因为使用枚举可以避免在代码中使用未知的硬编码常量。主要分为数字枚举、字符串枚举、异构枚举。

以下是一个简单的 TypeScript 枚举类型的例子:

enum Color {
    
    
  Red,
  Green,
  Blue
}

let c: Color = Color.Green;
console.log(c); // 1

(1)数字枚举:使用数字作为枚举成员的值。
enum Direction {
    
    
  Up,
  Down,
  Left,
  Right,
}


let value: Direction = Direction['Up']
let valueName = Direction[0]
console.log(value)//0
console.log(valueName)//Up
	

编译后,如下
在这里插入图片描述

由运行结果可以看到,我们既可以取到枚举成员的属性名,也能取到枚举成员的属性值,它们之间是存在相互映射的关系。

(2)字符串枚举:使用字符串作为枚举成员的值。
enum Color {
    
    
  Red = 'RED',
  Green = 'GREEN',
  Blue = 'BLUE',
}

	
let stringValueVal = Color['Red']
console.log(stringValueVal)//Red

在这里插入图片描述

需要注意的是,对于字符串类型的枚举,是不能对字符串类型枚举进行数字的反向映射。

(3)异构枚举:枚举类型里既包含字符串又包含数字。

注意:含有字符串值成员的枚举中也可以使用计算值。

enum BooleanLikeEnum {
    
    
  No = 0,
  Yes = "YES",
}

console.log(BooleanLikeEnum.No); // 0
console.log(BooleanLikeEnum.Yes); // "YES"

以上就是一个典型的异构,包含字符串和数字类型值。

同时注意,含有字符串成员值的枚举中允许使用计算值。


enum FileAccess {
    
    
  // 常量成员
  START,
  None = 'none',
  Read    = 1 << 1,
  Write   = 1 << 2,
  ReadWrite  = Read | Write,
  // 计算成员
  G = "123".length
}

console.log(FileAccess.Read); // 2
console.log(FileAccess.G); // 3

这种写法没问题,即可以使用计算值,也可以包含字符串值。
在这里插入图片描述

(4)计算值和常量成员

枚举对象的成员值可以是计算出来的值也可以是常量值,如上面例子显示,既包含了常量,也包含了计算量

enum FileAccess {
    
    
  // 常量成员
  None,
  Read    = 1 << 1,
  Write   = 1 << 2,
  ReadWrite  = Read | Write,
  // 计算成员
  G = "123".length
}

console.log(FileAccess.Read); // 2
console.log(FileAccess.G); // 3

3.5 void(空类型)

在 TypeScript 中,void 表示“没有返回值”的函数或表达式。

它通常用于函数声明和定义中,在函数签名中表示该函数不会返回任何值。

function sayHello(): void {
    
    
  console.log("Hello!");
}

在上面的示例中,sayHello() 函数不会返回任何值,因此可以使用 void 类型进行声明。

另外,void 类型的变量只能被赋值为 undefined 或 null:

let num: void = undefined;
let str: void = null;

3.6 never(不存在的值类型)

never 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。
这意味着声明为 never 类型的变量只能被 never 类型所赋值,在函数中它通常表现为抛出异常或无法执行到终止点(例如无限循环),示例代码如下:

let x: never;
let y: number;
// 编译错误,数字类型不能转为 never 类型
x = 123;
// 运行正确,never 类型可以赋值给 never类型
x = (()=>{
    
     throw new Error('exception')})();
// 运行正确,never 类型可以赋值给 数字类型
y = (()=>{
    
     throw new Error('exception')})();
// 返回值为 never 的函数可以是抛出异常的情况
function error(message: string): never {
    
    
    throw new Error(message);
}
// 返回值为 never 的函数可以是无法被执行到的终止点的情况
function loop(): never {
    
    
    while (true) {
    
    }
}
3.7 unknow(未知类型)

在 TypeScript 中,未知类型表示一个值可以是任何类型。与 any 类型不同的是,未知类型不能直接赋值给其他类型,除非对其进行类型检查或类型断言。

以下是一个使用未知类型的示例:

let x: unknown = 10;

// 使用 typeof 操作符检查类型
if (typeof x === 'number') {
    
    
  console.log(x + 5);
}

// 使用类型断言转换为其他类型
let y = x as string;
console.log(y.toUpperCase());

在上面的示例中,变量 x 被定义为未知类型,并赋值为数字 10。
在第一个 if 语句中,使用 typeof 操作符检查 x 是否为数字类型,如果是,则将其加 5 并输出。
在第二个语句中,使用类型断言将 x 转换为字符串类型,并使用 toUpperCase() 方法输出其大写形式。

编译后结果如下:
在这里插入图片描述


以上就是类型声明和应用,感兴趣的同学帮忙来个点赞关注,谢谢。




猜你喜欢

转载自blog.csdn.net/suwu150/article/details/131998408
今日推荐