16在 JS 项目中使用 TS(下)

163 阅读5分钟

一. React18的类型声明来自哪里

  • /node_modules/@types/react/index.d.ts
// 当装了第三方的js插件之后,如果没有types可以尝试通过安装@types来获取类型文件
// npm i react@18
// npm i -d @types/react@18
// 如果node_modules/xxx 没有提供类型声明,就会去node_modules/@types/xxx里去找

二. vue3俄的类型声明来自哪里

  • vue3和react不一样,vue3是直接用ts写的,里面包含了类型文件
  • /node_modules/vue/dist/vue.d.ts中,可以通过node_modules/vue/package.json的types字段来进行查找
// 安装
npm i vue@3

// 直接可以获得类型
import { createApp } from 'vue';
  • 总结: *.d.ts的来历有两种。

    • 源码是JS/Flow,只能s手写*.d.ts
    • 源码是TS-自动生成*.d.ts
      • tsc ./src/main.ts,这是生成js
      • 如果加上-d的选项tsc -d ./src/main.ts,那么就会生成js还会生成一个ts
      • 还可以用tsconfig等配置好的打包器,declaration: 'true',一般没有必要,因为我们不写库
  • 介绍tsconfig的官方文档

三. node.js的类型声明来自哪里

  • 需要先安装一下类型
npm i -d @types/node@18
  • 具体位置在/node_modules/@types/node/index.d.ts,通过reference引入
    • 这说明node的类型不像es6,dom被内置
    • node_modules/@types/里的目录自动加载,但是自动加载也有问题,如果类型文件太多了就会变得卡顿,可以通过配置tsconfig去解决
// 写进去之后才会加载 
"compilerOptions": {
  "types": ["node", "react", "react-dom", "jest"]
}
  • 这里如果说你没有写某个types,但是vscode也是别出来了类型。下面是一些可能的原因:

    • 默认类型声明文件: TypeScript 编译器内置了一些默认的类型声明文件,例如 lib.d.ts 和 dom.d.ts。这些文件包含了一些基本的类型信息,因此,当你在项目中没有显式指定 types 字段时,TypeScript 会默认引入这些内置的类型声明文件。
    • 自动引入依赖的类型声明: 如果你的项目使用了某个库或模块,而该库或模块本身包含了类型声明文件(通常是在 @types 组织中),TypeScript 编译器和 VSCode 会尝试自动找到并引入这些类型声明文件。
    • 智能推断: TypeScript 编译器和 VSCode 都具有智能推断的能力,可以基于代码内容进行类型推断。这意味着它们可以尝试理解你的代码并自动查找相应的类型信息,即使没有显式的 types 配置。
    • 基于项目的默认配置: 如果你使用了 TypeScript 的默认配置,那么它会尽可能地使用一些合理的默认值,包括默认的类型声明文件的引入。
    • 总体而言,TypeScript 和 VSCode 在没有显式 types 配置的情况下,会尽量通过一些内置规则和自动机制来获取和显示类型信息。虽然你可能没有在 tsconfig.json 中显式指定 types,但这并不妨碍 TypeScript 编译器和 VSCode 在大多数情况下找到和使用正确的类型声明文件。
  • 这里又会出现一个新的场景,如果tsconfig的types没有引入某个类型文件,但是又想使用这个第三方类型文件该怎么做

    • 手动引入: 在需要使用该类型声明文件的文件中,你可以直接使用 /// <reference> 来手动引入该声明文件。这会告诉 TypeScript 编译器在处理该文件时使用指定的类型声明。这种方法的缺点是需要手动在每个文件中引入,可能不够灵活。
/// <reference lib="node" />
/// <reference path="node" />
/// <reference type="node" />

// 这三种 /// <reference ... /> 的指令用于告诉 TypeScript 编译器在处理当前文件时应该使用的类型信息。
// 在实际使用中,通常你只需要选择其中一种引入方式,具体取决于你的项目需要使用的类型信息的来源。例如,如果你的项目使用了 Node.js,并且你不需要自定义类型声明文件,那么只需使用 /// <reference lib="node" /> 即可。如果你使用了某个第三方库,并且该库的类型声明文件在 @types 中,那么可以使用 /// <reference type="library-name" />。
  • 模块声明: 你可以在代码中使用 declare module 语法创建一个 ambient 模块声明,从而告诉 TypeScript 编译器某个模块的类型信息。这样,你可以在整个项目中使用这个类型信息,而无需在每个文件中手动引入。这个方法更加灵活,但仍然需要在项目中维护一个额外的声明文件。
declare module 'your-module-name' {
}

四. 总结四种给JS添加类型声明的方式

    1. global.d.ts声明全局变量
    1. types.d.ts声明全局类型
    • 如果import/export了,就 用`declare global``
    1. 用同名同名.d.ts声明模块类型,同名是指对应js文件s的同名
    1. @types/xxx 给 xxx 添加类型声明

五. 如果一个第三方js库没有类型文件,但是又想在ts中使用它该如何做

  • 方式1,自己去维护它的整个types,但是不建议,太耗费精力
  • 方式2. 拿react举例,假设react是对应的类型文件
// myReact.js,js种可以自由引入js文件
import React from 'react'
export default React

// myReact.d.ts
const React : {
  createElement: (x: String) => any
}
export default React

// main.ts
import React from './myReact'
React.createElement('123')
  • 这种方式,就是用js进行一个封装,我的类型只描述js中用到的东西,这里myReact作为一个中间文件,用到的东西

六. commonjs的使用类型方式

  • 这里不作详细说明,目前前端已经普及es module,此中方式node中用的多,如果把这块内容加入,会过于繁杂
  • 具体可以参考自行学习: ts.xcatliu.com/basics/decl…