如何在TypeScript中使用可选链?

21

看起来可选链已经到位了has landed这是一个例子

我无法弄清楚如何让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,并且不想引入它。

2个回答

28

问题在于你正在针对 esnext 进行编译,这会告诉编译器将所有语言特性输出为原样而不进行任何转译。将语言设置为 es2020(或更低版本),?.?? 将被转译为兼容的代码:

(async function () {
    let imageFileId = (await db.query(sql`select id from image_files where sha256=${sha256}`))[0]?.id;
})()

很遗憾,您无法对编译哪些语言功能和不编译哪些进行细粒度控制,您只能整体选择一个版本。

Playground Link


6
问题是我也在使用 BigInts,这已经被 Node 支持了一段时间了 :-( “TS2737: 当目标低于 ESNext 时,BigInt 字面量不可用。” - mpen
@mpen Babel 在支持选择语言特性方面做得更好。 - Titian Cernicova-Dragomir
8
升级到 TypeScript 3.8 之后,我又遇到了同样的问题。我认为你应该将目标设置为 es2019,以便“polyfill”可选链操作符。 - icl7126
4
@icl7126 是正确的。对于 TS 3.8.3,您需要将目标设置为 ES2019 - Nikita Cherednichenko
2
设置 target: ES2019 对于 TS 3.9.5 仍然有效。 - I'll Eat My Hat
显示剩余4条评论

5

我不想使用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的TypeScript Babel起始应用程序中复制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接