如何在 TypeScript 中使用可选链接?
Posted
技术标签:
【中文标题】如何在 TypeScript 中使用可选链接?【英文标题】:How to get optional chaining working in TypeScript? 【发布时间】:2020-03-02 16:12:14 【问题描述】:看起来像可选链接has landed。 Here's an example
我想不通的是如何让 TS 正确编译它。我的项目中没有出现任何语法错误,但是:
let imageFileId = (await db.query(sql`select id from image_files where sha256=$sha256`))[0]?.id;
输出为:
let imageFileId = (await db.query(mysql3_1.sql `select id from image_files where sha256=$sha256`))[0]?.id;
在我们获得 Node 的原生支持之前,它不会运行。
这是我的 tsconfig:
"compilerOptions":
"strict": true,
"importHelpers": false,
"inlineSources": true,
"noEmitOnError": true,
"pretty": true,
"module": "commonjs",
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": false,
"removeComments": false,
"preserveConstEnums": false,
"sourceMap": true,
"lib": ["es2018"],
"skipLibCheck": false,
"outDir": "dist",
"target": "esnext",
"declaration": false,
"resolveJsonModule": true,
"esModuleInterop": false,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths":
"*": ["src/*"]
,
"noEmit": false
,
"files": [
"src/index"
],
"include": [
"src/**/*.d.ts"
]
我需要启用其他选项来编译?.
运算符吗?
请注意我不使用 Babel,我不想把它带入图片。
【问题讨论】:
【参考方案1】:问题是您的目标是esnext
,这将告诉编译器按原样输出所有语言功能,而无需进行任何转译。将语言设置为 es2020(或更低),?.
和 ??
将被转译为兼容代码:
(async function ()
let imageFileId = (await db.query(sql`select id from image_files where sha256=$sha256`))[0]?.id;
)()
Playground Link
不幸的是,对于哪些语言特性被编译以及哪些语言特性不需要选择一个整体,没有细粒度的控制,
【讨论】:
问题是我也在使用节点支持一段时间的 BigInt :-( "TS2737: BigInt literals are not available when target below ESNext" @mpen 我只是在编辑我的答案来解决这个问题。不幸的是,没有办法控制哪些特定的语言特性被编译,哪些不被编译 升级到 TypeScript 3.8 后我又遇到了同样的问题。我认为您实际上应该以es2019
为目标,以便“填充”可选链接。
@icl7126 是对的。对于 TS 3.8.3,您必须将 ES2019
设置为目标
设置 target: ES2019
对于 TS 3.9.5 仍然适用【参考方案2】:
好吧,我不想使用 Babel,因为那样我就必须弄清楚如何替换 ts-node
。那里有一堆过时的文档提到旧的 Babel 包,但这些说明应该在 2019 年 11 月起生效:
添加.babelrc
文件:
"presets": [
["@babel/preset-env","targets": "node": "current"],
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-syntax-bigint"
]
添加这些部门:
"devDependencies":
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.0",
"@babel/node": "^7.7.0",
"@babel/plugin-syntax-bigint": "^7.4.4",
"@babel/preset-env": "^7.7.1",
"@babel/preset-typescript": "^7.7.0",
"@types/node": "^12.7.5",
"typescript": "^3.7.2"
执行您的代码:
node_modules/.bin/babel-node --extensions ".ts" src/index.ts
--extensions ".ts"
非常重要,即使您明确尝试执行一个 .ts 文件,它也不会在没有它的情况下对其进行转换。
我喜欢使用 GNU Make 而不是 package.json 脚本:
MAKEFLAGS += --no-builtin-rules
.SUFFIXES:
NM := node_modules/.bin
.PHONY: build start dev clean test publish
## commands
########################################
__default:
$(error Please specify a target)
build: build-types build-js dist/package.json
build-types: node_modules/.yarn-integrity
$(NM)/tsc --emitDeclarationOnly
build-js: node_modules/.yarn-integrity
$(NM)/babel src --out-dir dist --extensions ".ts" --source-maps inline
run: node_modules/.yarn-integrity
$(NM)/babel-node --extensions ".ts" src/index.ts
check: node_modules/.yarn-integrity
$(NM)/tsc --noEmit
dist:
mkdir -p $@
clean:
rm -rf node_modules dist yarn-error.log
dist/package.json: package.json | dist
jq 'del(.private, .devDependencies, .scripts, .eslintConfig, .babel)' $< > $@
## files
########################################
node_modules/.yarn-integrity: yarn.lock
@yarn install --frozen-lockfile --production=false --check-files
@touch -mr $@ $<
yarn.lock: package.json
@yarn check --integrity
@touch -mr $@ $<
或者只是从Microsoft's TypeScript Babel Starter复制。
【讨论】:
以上是关于如何在 TypeScript 中使用可选链接?的主要内容,如果未能解决你的问题,请参考以下文章
Vue 3.0.0.rc-5 中的 TypeScript 3.9.7 可选链接警告