TypeScript全解:JS&TS

d.ts 文件的妙用

默认情况下

*.d.ts 中的 type,interface 全局生效

// types.d.ts
type User = {
  name: string;
  age: number;
}
// main.ts
type A = User

但如果 *.d.ts 里有 import 或 export,则 User 只在当前模块生效

// types.d.ts
export type User = {
  name: string;
  age: number;
}
// main.ts
type A = User // TODO: 报错

但是加了import 或 export,还想全局生效怎么做?用 declare global

// types.d.ts
import x from 'vite'

type Local = string; // TODO: 注意这里不是全局的

declare global {
  interface User {
    name: string;
    age: number;
  }
}

d.ts 与 JS 文件结合

假设你已经有如下 JS 文件

// x.js
window.addOne = function (n) {
  return n + 1
}

现在你想在你的 TS 文件中直接使用,虽然功能上可以,但是会有类型报错

// main.ts
const result = addOne(1) // TODO: 报错,会提示你没有这个函数

所以我们需要声明一下

// global.d.ts
const addOne: (n: number) => number

// 等价于

type AddOne = (n: number) => number // 类型声明
const addOne:AddOne // 变量声明

这样的弊端就在,如果你这里的类型写错了,TS 也不能帮你检测出来

但是实际场景,已经没有人写这样的代码了,实际我们会遇到这样的 JS 文件

// x.js
const add = (a, b) => a + b
export { add }

如果我们在 TS 文件中直接使用,会提示你这是一个 JS 模块,没有类型,TS 不能直接使用

import { add } from './x'

所以我们一般会直接在同级目录下新建相同名字的 *.d.ts

// x.d.ts

const add: (a: number, b: number) => number

export { add }

这样 TS 就能帮你自动建立关联

d.ts 与 浏览器

当我们有如下代码的时候,这里的类型哪里来的呢?

const app = document.getElementById('app') // TODO: 这里的 app 直接就有类型了

是 tsconfig 里面加载好了的

// tsconfig.json
{
  "compilerOptions": {
    "lib": ["ESNext", "DOM"] // 这里的 DOM
  }
}

那这个 DOM 相关的文件哪里来的呢?

是社区的程序员们一行一行写好的,然后要么通过 github 上下载下来的,或从 npm 下载下来的,这样我们才能很舒服的写代码,如果没有这些文件,最基础的 JS 代码都没有类型提示

*.d.ts + JS + React

正常我们是无法在 TS 中使用 React 的,因为 React 源码是用的 flow,而不是 TS

import React from 'react' // TODO: 报错

但是我们可以通过 npm add -D @types/react,就能解决这个问题

所以说如果 node_modules/xxx 如果没有提供类型声明,就会去 node_modules/@types/xxx 去寻找

这也是 React 团队的解决思路,但是比不上 Vue 团队的方案好

*.d.ts + JS + Vue3

我们下载完后发现可以直接使用

import { createApp } from 'vue'

通过看包的源码得:

原来是 vue 的 package.json 声明了 types 属性,所以我们就不用额外下载关联了

小结

  • *.d.ts 的来历
    • 源码是 JS/Flow
      • 手写 *.d.ts
    • 源码是 TS
      • 自动生成 *.d.ts
      • tsc -d x.ts
      • tsconfig

*.d.ts 与 Node.js

import * as fs from 'fs' // TODO: 报错

Node 也是一样,需要安装 @types/node,和 React 一样,为什么还要单独讲呢?我们看一下源码

可以看到里面有一堆的 reference,这些是干嘛用的呢?

  • reference lib -- 引入一个 lib(有点像 tsconfig 里面的 lib 选项)
  • reference path -- 引入一个相对路径的文件
  • reference types="node" -- 引入一个 types(有点像 tsconfig 里面的 types 选项)

Node 为什么要用这么奇怪的语法呢?
因为早些年 TS 出生的时候,那个时候还没有 ES modules,所以 TS 不得不发明一种模块引入语法

如果你的 tsconfig 里 types里没有没有包涵你想使用的类型,如:node,你可以这样手动添加

/// <reference types="node"
import * as fs from 'fs'

总结

给 JS 添加类型声明的方式

  • 用 global.d.ts 声明全局变量
  • 用 types.d.ts 声明全局类型
    • 如果 import / export 了,就用 declare global
  • 用 同名.d.ts 声明类型模块
  • 用 @types/xxx 给 xxx 添加类型声明
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容