Как заставить работать опциональную цепочку в TypeScript?

Похоже, дополнительное связывание выполнено. здесь

Я не могу понять, как заставить 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 и не хочу делать это на картинке.


person mpen    schedule 06.11.2019    source источник


Ответы (2)


Проблема в том, что вы нацеливаетесь на esnext, это скажет компилятору вывести все языковые функции как есть, без какой-либо транспиляции. Установите язык es2020 (или ниже), и ?. и ?? будут преобразованы в совместимый код:

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

площадка Link

Нет точного контроля над тем, какие языковые функции будут транслироваться, а какие нет, к сожалению, вам нужно выбирать версию в целом,

person Titian Cernicova-Dragomir    schedule 06.11.2019
comment
Проблема в том, что я также использую BigInts, которые уже некоторое время поддерживаются узлом :-( TS2737: литералы BigInt недоступны при таргетинге ниже ESNext - person mpen; 06.11.2019
comment
@mpen Я как раз редактировал свой ответ, чтобы решить эту проблему. К сожалению, нет способа контролировать, какие конкретные языковые функции компилируются, а какие нет. - person Titian Cernicova-Dragomir; 06.11.2019
comment
@mpen Babel лучше поддерживает выбор и выбор в отношении языковых функций. - person Titian Cernicova-Dragomir; 06.11.2019
comment
У меня снова возникла та же проблема после обновления до TypeScript 3.8. Я думаю, вам нужно на самом деле нацелить es2019, чтобы полифилить необязательную цепочку. - person icl7126; 02.03.2020
comment
@ icl7126 прав. Для TS 3.8.3 необходимо установить ES2019 в качестве цели - person Nikita Cherednichenko; 16.03.2020
comment
настройка target: ES2019 по-прежнему актуальна для TS 3.9.5 - person I'll Eat My Hat; 13.06.2020
comment
@ I'llEatMyHat изменил ответ, чтобы отразить, что любая версия ниже es2020 будет работать, просто esnext сохраняет исходные операторы. - person Titian Cernicova-Dragomir; 13.06.2020
comment
Я имею в виду, что ES2020 у меня не работает. Только ES2019 и ниже. ES2020 приводит к ошибке You may need an additional loader to handle the result of these loaders. - person I'll Eat My Hat; 14.06.2020
comment
Кажется, это связано с этим вопросом, который относится к PR зависимости веб-пакета - person I'll Eat My Hat; 14.06.2020

Что ж, я не хотел использовать Babel, потому что тогда мне пришлось бы придумать, как заменить ts-node. Существует множество устаревших документов, относящихся к старым пакетам Babel, но эти инструкции должны работать с ноября 2019 года:

Добавьте .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 Starter.

person mpen    schedule 06.11.2019