首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【TypeScript】本篇文章带你速通TypeScript,了解TS与JS的关系,TS如何定义类型、接口、枚举...

【TypeScript】本篇文章带你速通TypeScript,了解TS与JS的关系,TS如何定义类型、接口、枚举...

作者头像
用户11865655
发布2025-10-13 17:01:03
发布2025-10-13 17:01:03
5500
代码可运行
举报
文章被收录于专栏:CSDN专栏CSDN专栏
运行总次数:0
代码可运行

1. TS是什么

TS是包含了JS的内容的,或者说TS是在JS上做的改进

  1. TypeScript 由微软开发,是基于JavaScript的一个扩展语言
  2. TypeSCript包含了JS的所有内容;
  3. TypeScript增加了:静态类型接口、泛型等很多现代开发特性,因此更适合大型项目的开发
  4. TypeScript需要编译为JavaScript,然后交给浏览器或其他JavaScript运行环境执行

1.1 市场需求

JS在诞生时的定位是浏览器脚本语言,用于在网页中浅入一些简单的逻辑,而且代码量很少

现如今的JS应用场景比以前丰富太多,代码量也比以前大很多。而当时JS就没有考虑倒如今的应用场景和代码量,逐渐出现了很多缺点;

1.1.1 JS的缺点

不清不楚的数据类型

代码语言:javascript
代码运行次数:0
运行
复制
let s = "hello"
s() // 报错:TypeError: s is not a function

在代码量少的时候可以很清晰的看见这是一个字符串不是一个方法,会报错 而当代码量多了后,真的出现调用这种情况时如何定位?

有漏洞的逻辑

代码语言:javascript
代码运行次数:0
运行
复制
const str = Date.now() % 2 ? '奇数' : '偶数'

if(str!=='奇数'){
    alert('hello')
}else if (str==='偶数'){
    alert('world')
}

判断是否是偶数,其实else if内的代码块永远不会被执行 当命中第一个if时,else if就不会被执行了 那么,在这时 JS 并不会给出任何的逻辑上的提示

访问不存在的属性(普遍是null)

代码语言:javascript
代码运行次数:0
运行
复制
const obj = { width: 10, height: 15};
const area = obj.width * obj.heighth;

在JS里,如果出现调用一个不存在的属性,一样不会给出任何的提示 哪怕出现的是一个错误的、不可计算的结果

低级的拼写错误

代码语言:javascript
代码运行次数:0
运行
复制
const message = 'hello, world';
message.toUperCase();// 正确的方法名称:.toUpperCase();

如果出现拼写错误,导致无法调用函数,JS一样不会给出任何提示

1.1.2 TS的优势
  1. 不清不楚的数据类型
在这里插入图片描述
在这里插入图片描述
  1. 有漏洞的逻辑
在这里插入图片描述
在这里插入图片描述
  1. 访问不存在的属性(普遍是null)
在这里插入图片描述
在这里插入图片描述
  1. 低级的拼写错误
在这里插入图片描述
在这里插入图片描述
1.1.2.1 静态代码检查

TS能够解决上述JS出现的问题,这源于TS使用了【静态代码检查】功能

  • 在代码运行前进行检查,发现代码的错误或不合理性,减小运行时异常出现的机率,这种检查叫做【静态类型检查】,TS的核心就是【静态代码检查】,简单来说就是把运行时的错误前置
  • 但同样的,TS的代码量要大于JS,但由于TS的代码结构更加清晰,在**后期代码的维护中TS却远胜于JS**

2. TS的编译

2.1 命令行编译

  • 使用 tsc 命令

在使用 tsc 命令前,还需要安装ts环境 npm i typescript -g

代码语言:javascript
代码运行次数:0
运行
复制
tsc ts文件名

使用后,会相同文件夹下编译生成一个js文件

  • ts文件
代码语言:javascript
代码运行次数:0
运行
复制
var a = 10;
console.log("数字是:"+a)
  • 生成的js文件
代码语言:javascript
代码运行次数:0
运行
复制
var a = 10;
console.log("数字是:" + a);

2.2 自动化编译

命令

说明

tsc --init

生成自动化配置文件

tsc --watch [ts文件]

监视某一个ts文件,当ts文件发生任何改动,都会实时生成JS

tyc --noEmitOnError – watch

当编译出错时不生成 .js 文件(不推荐,更建议修改tsconfig.json中的noEmitOnError配置)

  • 默认的tsconfig.json
代码语言:javascript
代码运行次数:0
运行
复制
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig to read more about this file */

    /* Projects */
    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */

    /* Language and Environment */
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
    // "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */

    /* Modules */
    "module": "commonjs",                                /* Specify what module code is generated. */
    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
    // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
    // "rewriteRelativeImportExtensions": true,          /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
    // "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
    // "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
    // "customConditions": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
    // "noUncheckedSideEffectImports": true,             /* Check side effect imports. */
    // "resolveJsonModule": true,                        /* Enable importing .json files. */
    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */

    /* JavaScript Support */
    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */

    /* Emit */
    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
    // "removeComments": true,                           /* Disable emitting comments. */
    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */

    /* Interop Constraints */
    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
    // "verbatimModuleSyntax": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
    // "isolatedDeclarations": true,                     /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */

    /* Type Checking */
    "strict": true,                                      /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
    // "strictBuiltinIteratorReturn": true,              /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */

    /* Completeness */
    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
  }
}

3. 类型声明

3.1 基本定义

代码语言:javascript
代码运行次数:0
运行
复制
let a: string
let b: number
let c: boolean

a = 'hello'
b = 100
c = true
console.log(a,b,c)// hello 100 true

限定函数的参数类型

代码语言:javascript
代码运行次数:0
运行
复制
function count(x:number,y:number){
    return x+y
}
let result = count(1,2)
console.log(result)// 3

限定函数的返回类型

代码语言:javascript
代码运行次数:0
运行
复制
function count(x:number,y:number):string{
    return x+y+"数量"
}
let result = count(1,2)
console.log(result)

字面量类型

代码语言:javascript
代码运行次数:0
运行
复制
let a: string
let b: 'test'

a = 'hello'
b = 'name'

当类型限定为一个字面量常量时,那么该变量只会是这个字面量常量值,不可发生改变

在这里插入图片描述
在这里插入图片描述

3.2 类型推断

TS会根据我们的代码,进行类型推导,例如下面代码中的变量d,只能存储数字

代码语言:javascript
代码运行次数:0
运行
复制
let d = -99
d = false // 报错

请注意,类型推断不是万能的,面对复杂类型时推断容易出问题,所以尽量还是明确的编写类型声明

代码语言:javascript
代码运行次数:0
运行
复制
let d: number = -99
d = false // 报错

4. 类型总览

4.1 JS中的数据类型

关键字

说明

string

字符串

number

数量

boolean

布尔

null

undefined

未定义

bigint

大整形

symbol

标记

object

对象

object类型中,还包含:ArrayFunctionDate

4.2 TS中的数据类型

  • JS有的数据类型,TS中都有

新增了下述类型

关键字

说明

any

任意类型

unknown

未知

never

不存在值的类型

void

没有类型

tuple

数组

enum

枚举

type

类型

interface

接口

在JS中的内置构造函数:NumberStringBoolean,它们会用于创建对应的包装对象,在日程开发时很少使用,在TS中也是同理,所以TS中进行类型声明时,通常都是用小写的numberstringboolean

代码语言:javascript
代码运行次数:0
运行
复制
let a: string = 'a'; // TS更加推荐这种
let b = new String('b');// String是一个包装类
let c: String = 'c';// 使用的包装类,不推荐;更加占用资源
  • 原始类型 和 包装对象
    • 原始对象:如 numberstringboolean 在JS中是简单的数据类型,它们在内存中占用空间少,处理速度快
    • 包装对象:如 NumberStringBoolean 是复杂类型,在内存中占用更多的空间
  • 自动装箱:JS在必要时会自动将原始类型包装成对象,以便调用方法或访问属性

5. 常用类型

5.1 any

  • any 的含义是:任意类型,一旦将变量类型限制为any,那就意味着放弃了对改变了的类型检查
代码语言:javascript
代码运行次数:0
运行
复制
let a: any
a = 100
a = "你好"
a = false

// 如果不加任何的类型限定,默认就是 【any】类型
let b
b = 100
b = "你好"
b = false

注意:any类型的变量,可以复制给任意类型的变量

代码语言:javascript
代码运行次数:0
运行
复制
let a: any
a = false

let c: string
c = a

5.2 unknown

  • unknown的含义是:未知类型

可以将unknown理解为一个类型安全的any,适用于:不确定数据的具体类型

代码语言:javascript
代码运行次数:0
运行
复制
let a: unknown
a = 100
a = "你好"
a = false

let c: string
c = a // 警告,不能将类型“unknwon”分配给类型“string”

不过也可以赋值,需要进行判断或者断言

判断

代码语言:javascript
代码运行次数:0
运行
复制
let a: unknown
a = 100
a = false
a = "你好"

let c: string

// 判断
if(typeof a === 'string'){
    c = a
}

断言

代码语言:javascript
代码运行次数:0
运行
复制
let a: unknown
a = 100
a = false
a = "你好"

let c: string
c = a as string // 断言
c = <string> a // 断言

调用函数时,也和any存在不同

代码语言:javascript
代码运行次数:0
运行
复制
let str1: string
str1 = 'hello'
str1.toUpperCase() // 无警告

let str2: any
str2 = 'hello'
str2.toUpperCase() // 无警告

let str3: unknown
str3 = 'hello'
str3.toUpperCase() // 警告:“str3”的类型为“未知”

5.3 never

  • never的含义是:任何值都不是(不能有值)

几乎不用never去直接限制变量,因为没有意义:

代码语言:javascript
代码运行次数:0
运行
复制
let a: never

a = 1
a = true
a = undefined
a = null

never一般是TypeScript主动推断出来的

代码语言:javascript
代码运行次数:0
运行
复制
let a: string

a = 'hello'
if(typeof a==='string'){
    console.log(a.toLowerCase())
}else{
    // 这里推断出来时 never,因为没有任何一个值会符合此处的逻辑
    console.log(a)
}

never也可用于限制函数的返回值

代码语言:javascript
代码运行次数:0
运行
复制
function throwError(str: string):never{
    throw new Error("程序异常退出:"+str)
}

never作为返回值,一般来说,就是在这个方法无法正常结束的时候才符合标准

5.4 void

void 通常用于函数返回值声明,含义:【函数不返回任何值,调用者也不应该依赖其返回值进行任何操作】

代码语言:javascript
代码运行次数:0
运行
复制
function logMessage(msg: string):void{
    console.log(msg)
}
logMessage('hello');

编码者没有编写return去制定函数的返回值,所以logMessage函数时没有显示返回值的,但会有一个隐式返回值,就是undefined;即:虽然函数返回类型为void,但也可以接收undefined,简单点来说:undefined 是 void 可以接收的一种 “空”

以下三种方式声明是没有问题的

代码语言:javascript
代码运行次数:0
运行
复制
function logMessage1(msg: string):void{
    console.log(msg)
}
function logMessage2(msg: string):void{
    console.log(msg)
    return
}
function logMessage3(msg: string):void{
    console.log(msg)
    return undefined
}

void函数返回值无法进行任何操作

代码语言:javascript
代码运行次数:0
运行
复制
////////////////////////////////void///////////////////////////////////
function logMessage4(msg: string):void{
    console.log(msg)
}
let s1 = logMessage4("hello")
if(s1){ // 警告:无法测试 "void" 类型的表达式的真实性
    console.log("logMessage4");
}
////////////////////////////////undefined///////////////////////////////////
function logMessage5(msg: string):undefined{
    console.log(msg)
}
let s = logMessage5("hello")
if(s){
    console.log("logMessage5");
}

理解void与undefined

  • void是一个广泛的概念,用来表达“空”,而undefined则是这种“空”的具体实现之一
  • 因此可以说undefinedvoid能接收的“空”状态的一种具体形式
  • 换句话说:void包含undefined,但void表达的语义超越了单纯的undefined,它是一种意图上的约定,而不仅仅是特定值的限制

总结:

若函数返回类型是void那么:

  1. 从语法上讲,函数是可以返回undefined
  2. 从语义上讲,函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作,即使返回了undefined

5.5 object和Object

关于objectObject,实际开发中使用的相对较少,因为范围太大了

5.5.1 object

object的含义是:所有非原始数据类型 都可以存储:对象、函数等

代码语言:javascript
代码运行次数:0
运行
复制
let a:object

a = {}
a={name:"张三"}
a=[1,2,3,4,5]
a=function(){}
a=new String("12")
class Person{}
a = new Person()

/////////////// 无法使用 ////////////////
a = 1
a = false
a = "hello"
a = null
a = undefined
5.5.2 Object
  • 官方描述:所有可以调用Object方法的类型
  • 简单记忆:除了undefinednull的任何值
  • 由于限制的范围太大,所以实际开发中使用的频率极低
代码语言:javascript
代码运行次数:0
运行
复制
let a:Object

a = {}
a={name:"张三"}
a=[1,2,3,4,5]
a=function(){}
a=new String("12")
class Person{}
a = new Person()
a = 1
a = false
a = "hello"

/////////////// 无法使用 ////////////////
a = null
a = undefined
5.5.3 声明对象类型

通用模式:

代码语言:javascript
代码运行次数:0
运行
复制
let person1: {name: string,age:number}
person1 = {name: "zhangsan",age: 18}

////////// 两种:带或不带 ? ///////////////
let person2: {name: string,age?:number}
person2 = {name: "zhangsan"}

索引签名:

允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性(具有动态属性的对象)

代码语言:javascript
代码运行次数:0
运行
复制
let person3: {
    name: string,
    age?: number,
    // 索引签名
    [key:string]:any
}

person3 = {name:"zhangsan",age:18,address:"湖南"}
5.5.4 声明函数类型
代码语言:javascript
代码运行次数:0
运行
复制
let count: (a:number,b:number) => string // 规定了函数的数据类型,参数类型是number,返回值类型是string类型

count = (x,y)=>{
    return x+y+"字符串"
}
  • TS 中的 => 在函数类型声明时表示函数类型,描述其参数类型和返回类型
  • JS中的 => 是一种定义函数的语法,是具体的函数实现
  • 函数类型声明还可以使用:接口、自定义类型等方式
3.5.5 声明数组类型
代码语言:javascript
代码运行次数:0
运行
复制
 let arr1: string[] // 规定了类型:数组内的每一项必须是字符串
 let arr2: Array<string>
 
 arr1 = ["a","b","c"]
 arr2 = ['hello','world']

上述代码中的Array<string>属于泛型

5.6 tuple

元组(Tuple)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。

元组用于精确描述一组值的类型,? 表示可选元素

代码语言:javascript
代码运行次数:0
运行
复制
let arr1: [string,number]
let arr2: [number,boolean?]
let arr3: [number,...string[]]

arr1 = ["hello",1]
arr2 = [100,false]
arr2 = [20]
arr3 = [100,"hello","world"]
arr3 = [100]

5.7 enum

枚举(enum)可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护

如下代码的功能是:根据调用walk时传入的不同参数,执行不同的逻辑。

存在的问题是调用walk时传参时没有任何提示,编码者很容易写错字符串内容,并且用于判断逻辑的updownleftright时连续且相关的一组值,那么这个时候**使用枚举(enum)**就非常的适用

代码语言:javascript
代码运行次数:0
运行
复制
function walk(str:string){
    if(str === 'up'){
        console.log("上");
    }else if(str === 'down'){
        console.log("下");
    }else if(str === 'right'){
        console.log("右");
    }else if(str === 'left'){
        console.log("左");
    }else{
        console.log("未知");
    }
}

walk("up")
walk("down")
walk("right")
walk("left")
5.7.1 数字枚举

数字枚举一种最常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点

代码语言:javascript
代码运行次数:0
运行
复制
enum Direction{
    UP,
    DOWN,
    LEFT,
    RIGHT
}
console.log(Direction)
/*
{
    "0": "UP",
    "1": "DOWN",
    "2": "LEFT",
    "3": "RIGHT",
    "UP": 0,
    "DOWN": 1,
    "LEFT": 2,
    "RIGHT": 3
}
*/
console.log(Direction.UP);// 0
console.log(Direction[0]);// UP

// 报错代码:
Direction.UP = 1 // 枚举中的值是只读的

使用数字枚举完成walk函数的逻辑,可以发现:代码更加直观易读,而且类型安全,同时更加易于维护

代码语言:javascript
代码运行次数:0
运行
复制
function walk(data:Direction){
    if(data === Direction.UP){
        console.log("上");
    }else if(data === Direction.DOWN){
        console.log("下");
    }else if(data === Direction.RIGHT){
        console.log("右");
    }else if(data === Direction.LEFT){
        console.log("左");
    }else{
        console.log("未知");
    }
}

walk(Direction.UP)
walk(Direction.DOWN)
walk(Direction.RIGHT)
walk(Direction.LEFT)
5.7.2 字符串枚举

枚举成员的值是字符串

代码语言:javascript
代码运行次数:0
运行
复制
enum Direction1{
    UP1 = "UP",
    DOWN1 = "DOWN",
    LEFT1 = "LEFT",
    RIGHT1 = "RIGHT"
}


/*
{
    "UP": "UP",
    "DOWN": "DOWN",
    "LEFT": "LEFT",
    "RIGHT": "RIGHT"
}
*/
console.log(Direction1)

let dir: Direction1 = Direction1.UP1
console.log(dir) // 输出:“UP”
5.7.3 常量枚举

官方描述:常量枚举是一种特殊枚举类型,它使用const关键字定义,在编译时会被内联,避免生成一些额外的代码。

  • 何为编译时内联?

所谓 “内联”,其实就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。这可以减少生成的JS代码量,并提高运行时性能

5.8 type

type 可以为任意类型创建别名,让代码更简介,可读性更强,同时能更方便地进行类型复用和扩展。

5.8.1 基本用法

类型别名使用type关键字定义,type后跟类型名称,例如下面代码中的num是类型别名

代码语言:javascript
代码运行次数:0
运行
复制
type num = number
let price: num
price = 100
5.8.2 联合类型

联合类型是一种高级类型,它表示一个值可以是几种不同的类型之一

代码语言:javascript
代码运行次数:0
运行
复制
type Area = {
    height: number;
    width: number;
}
type Address = {
    num: number;
    cell: number;
    room: string;
}

// 代表test类型,只能是Area类型或者Address类型其中一种
type test = Area | Address
// 代表House类型,必须包含Area和Address两种类型
type House = Area & Address
let x: House = {
    height: 100,
    width: 20,
    num: 1,
    cell: 123,
    room: "008"
}

特殊点:

使用类型声明限制函数返回值为 void 时,TypeScript 并不会严格要求函数返回空

代码语言:javascript
代码运行次数:0
运行
复制
type LogFunc = () => void

const f1:LogFunc = function(){
    return 66 // ?void不是只能接受返回undefined吗,怎么这里返回number类型不报错
}

WHY?为什么可以这样? 其实是为了确保 Array.prototype.forEach 方法其回调的返回类型是void 保证能够正常运行

6. 类的相关知识

代码语言:javascript
代码运行次数:0
运行
复制
class Person{
    name: string;
    age: number;
    // 基本构造函数
    constructor(name: string,age: number){
        this.name = name
        this.age = age
    }
    speak(){
        console.log(`我叫:${this.name},今年${this.age}岁`);
    }
}

class Student extends Person{
    grade: string;
    constructor(name: string,age: number,grade: string){
        super(name,age) // 继承父类,必须使用super()方法
        this.grade = grade
    }
    study(){
        console.log(`${this.name} 正在努力学习中...`);
    }
}

const s = new Student("张三",15,"一年级")
s.speak() // 我叫:张三,今年15岁
s.study() // 张三 正在努力学习中..
console.log(s);
/**
{
    "name": "张三",
    "age": 15,
    "grade": "一年级"
}
*/
console.log(s.grade);// 一年级

6.1 属性修饰符

修饰符

含义

具体规则

public

公开的

可以被:类内部、子类、类外部访问

protected

受保护的

可以被:类内部、子类访问

private

私有的

可以被:类内部访问

readonly

只读属性

属性无法修改

6.1.1 public 修饰符
代码语言:javascript
代码运行次数:0
运行
复制
class Person{
    public name: string;
    age: number;
    // 基本构造函数
    constructor(name: string,age: number){
        this.name = name
        this.age = age
    }
    speak(){
        console.log(`我叫:${this.name},今年${this.age}岁`);
    }
}
const p1 = new Person("张三",18)
// 类的外部,可以访问public修饰的属性
console.log(p1.name)
6.1.2 属性简写模式:
代码语言:javascript
代码运行次数:0
运行
复制
class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}
////////////// 简写后 /////////////
class Person1 {
    constructor(
        public name: string,
        public age: number
    ) {
    }
}
6.1.3 protected 修饰符
代码语言:javascript
代码运行次数:0
运行
复制
class Person {
    constructor(protected name: string,protected age: number) {}

    protected getDetails(){
        return `我叫:${this.name},年龄是:${this.age}`
    }

    introduce(){
        console.log(this.getDetails);
    }
}
const p1 = new Person("tom",18)
p1.introduce()

// 无法访问,因为这些属性都是受保护的(protected)
// p1.name
// p1.age
// p1.getDetails

子类是否可以调用?

代码语言:javascript
代码运行次数:0
运行
复制
class Person {
    constructor(protected name: string,protected age: number) {}

    protected getDetails(){
        return `我叫:${this.name},年龄是:${this.age}`
    }

    introduce(){
        console.log(this.getDetails);
    }
}

class Student extends Person{
    study(){
        this.introduce()
        console.log(`${this.name}正在努力学习`);
    }
}

const s1 = new Student("cat",10)
s1.study()

回答是不可以

6.1.4 private 修饰符
代码语言:javascript
代码运行次数:0
运行
复制
class Person {
    constructor(
        protected name: string,
        public age: number,
        private IDCard: string
    ) {}

    private getPrivateInfo(){
        return `身份证号码为:${this.IDCard}`
    }

    getInfo(){
        return `我叫:${this.name},今年刚满${this.name}岁`
    }

    getFullInfo(){
        return this.getInfo+","+this.getPrivateInfo()
    }
}

const p1 = new Person("tom",18,"1231231233441")
// p1.name // 无法访问 protected
// p1.age // 可访问
// p1.IDCard // 无法访问 private

console.log(p1.getInfo());
console.log(p1.getFullInfo());
// p1.getPrivateInfo(); // 无法使用 private
6.1.5 readonly 修饰符
  • 说白了就是只读
代码语言:javascript
代码运行次数:0
运行
复制
class Person {
    constructor(
        protected readonly name: string,
        public readonly age: number,
        private IDCard: string
    ) {}
}

6.2 abstract 抽象类

概述:

  • 抽象类是一种无法被实例化的类,专门用来定义类的结构和行为,类中可以写抽象方法,也可以写具体实现,抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现其中的抽象方法

简记:

  • 抽象类不能实例化,其意义是可以被继承,抽象类里可以有普通方法,也可以有抽象方法
代码语言:javascript
代码运行次数:0
运行
复制
abstract class Animal{
    constructor(
        public name:string,
        public age:number,
        public type: string
    ){}

    abstract shout(): string

    do(){
        console.log(`一只叫做${this.name}的${this.type}开始发出:${this.shout()}的声音`);
    }
}
class Cat extends Animal{
    constructor(
        name:string,
        age:number,
    ){ super(name,age,"猫") }

    shout(): string {
        return "喵~~";
    }
}

const c1 = new Cat("蛋黄",3)
c1.do()

什么时候使用抽象类?

  1. 定义通用接口:为一组相关的类定义通用的行为(方法或属性)时
  2. 提供基础实现:在抽象类中提供某些方法或为其提供基础实现,这样派生类就可以继承这些实现
  3. 确保关键实现:强制派生类实现一些关键行为
  4. 共享代码和逻辑:当多个类需要共享部分代码时,抽象类可以避免代码重复

6.3 interface 接口

interface是一种定义结构的方式,主要作用是为:类、对象、函数等规定一种规范,这样可以确保代码的一致性和类型安全

但要注意interface只能定义格式,不能包含任何实现!

代码语言:javascript
代码运行次数:0
运行
复制
interface IPerson{
    name: string,
    age: number,
    number(n:number):void
}

class Person implements IPerson{
    
    constructor(
        public name: string,
        public age: number,
    ){}

    number(n: number): void {
        console.log(`测试:${n}`);
    }
}

const p = new Person("张三",18)
p.number(12)

同时,在TS中接口还可以当作对象使用

代码语言:javascript
代码运行次数:0
运行
复制
const p1: IPerson = {
    name: "张三",
    age: 18,
    number: function (n: number): void {
        console.log(`测试:${n}`);
    }
}

与其他语言不一样,TS里,接口名是可以重复的

官方叫做接口合并,意思是,相同接口名的接口都必须实现对应的属性

代码语言:javascript
代码运行次数:0
运行
复制
interface IPerson{
    name: string,
    age: number,
    number(n:number):void
}
interface IPerson{
    grender: string
}

什么时候使用接口:

  1. 定义对象的格式:描述数据模型、API响应格式、配置对象…
  2. 类的规范:规定一个类需要实现哪些属性和方法
  3. 自动合并:一般用于扩展第三方库的类型
6.3.1 interface 与 type 的区别
  • 相同点:interfacetype 都可以用于定义对象结构,两者在许多场景中是可以互换的。
  • 不同点:
    1. interface:更专注于定义对象和类的结构,支持继承、合并
    2. type:可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并
6.3.2 interface 与 抽象类 的区别
  • 相同点:都用于定义一个类的格式
  • 不相同:
    1. 接口:只能描述结构,不能有任何实现代码,一个类可以实现多个接口
    2. 抽象类:既可以包含抽象方法,也可以包含具体方法,一个类只能继承一个抽象类

7. 泛型

泛型允许我们在定义函数、类或接口时,使用类型参数来表示未指定的类型,这些参数在具体使用时,才被制定具体的类型,泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性

代码语言:javascript
代码运行次数:0
运行
复制
const f = <T,U>(a:T,b:U)=>{
    console.log(a,b);
}

// 使用泛型,指定传入方法内的类型
f<number,string>(1,"zhangsan")
f<number,number>(1,22)

泛型类:

代码语言:javascript
代码运行次数:0
运行
复制
class Person<T>{
    constructor(
        public name: string,
        public age: number,
        public extraInfo: T
    ){}

    speak(){
        console.log(`我叫:${this.name}今年${this.age}岁了`);
        console.log(this.extraInfo);
    }
}
const p1 = new Person<number>("tom",30,100)

type JobInfo = {
    title: string,
    company: string,
}
const p2 = new Person<JobInfo>("tom",30,{title:"程序员",company:"华为"})

在实例化对象时,定义了什么泛型类,就必须传入对应的类型数据

8. 类型声明文件

类型声明文件时 TS 中的一种特殊文件,通常以.d.ts作为扩展名。

它的主要作用是为现有的JS代码提供类型信息,使得TS能够在使用这些JS库或模块时进行类型检查和提示

  • index.html
代码语言:javascript
代码运行次数:0
运行
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!--type需要更改为 module-->
    <script type="module" src="./index.js"></script>
</body>
</html>
  • index.ts
代码语言:javascript
代码运行次数:0
运行
复制
import {add,mul} from './demo.js'

console.log(add(1,2));
console.log(mul(1,2));
  • demo.js
代码语言:javascript
代码运行次数:0
运行
复制
export function add(a,b){
    return a+b;
}

export function mul(a,b){
    return a*b;
}
  • demo.d.ts 【类型声明文件】
代码语言:javascript
代码运行次数:0
运行
复制
declare function add(a:number,b:number):number
declare function mul(a:number,b:number):number

export{add,mul};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. TS是什么
    • 1.1 市场需求
      • 1.1.1 JS的缺点
      • 1.1.2 TS的优势
  • 2. TS的编译
    • 2.1 命令行编译
    • 2.2 自动化编译
  • 3. 类型声明
    • 3.1 基本定义
    • 3.2 类型推断
  • 4. 类型总览
    • 4.1 JS中的数据类型
    • 4.2 TS中的数据类型
  • 5. 常用类型
    • 5.1 any
    • 5.2 unknown
    • 5.3 never
    • 5.4 void
    • 5.5 object和Object
      • 5.5.1 object
      • 5.5.2 Object
      • 5.5.3 声明对象类型
      • 5.5.4 声明函数类型
      • 3.5.5 声明数组类型
    • 5.6 tuple
    • 5.7 enum
      • 5.7.1 数字枚举
      • 5.7.2 字符串枚举
      • 5.7.3 常量枚举
    • 5.8 type
      • 5.8.1 基本用法
      • 5.8.2 联合类型
  • 6. 类的相关知识
    • 6.1 属性修饰符
      • 6.1.1 public 修饰符
      • 6.1.2 属性简写模式:
      • 6.1.3 protected 修饰符
      • 6.1.4 private 修饰符
      • 6.1.5 readonly 修饰符
    • 6.2 abstract 抽象类
    • 6.3 interface 接口
      • 6.3.1 interface 与 type 的区别
      • 6.3.2 interface 与 抽象类 的区别
  • 7. 泛型
  • 8. 类型声明文件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档