Использовать командующий в машинописном тексте

Я пытаюсь использовать командующий в машинописном тексте, и я хотел бы дать правильный тип своему кли. Итак, я начинаю с этого кода:

import * as program from "commander";

const cli = program
  .version("1.0.0")
  .usage("[options]")
  .option("-d, --debug", "activate more debug messages. Can be set by env var DEBUG.", false)
  .parse(process.argv);

console.log(cli.debug)

Но я получаю эту ошибку:

example.ts(9,17): error TS2339: Property 'debug' does not exist on type 'Command'.

Поэтому я попытался добавить интерфейс, как описано здесь:

import * as program from "commander";

interface InterfaceCLI extends commander.Command {
  debug?: boolean;
}

const cli: InterfaceCLI = program
  .version("1.0.0")
  .usage("[options]")
  .option("-d, --debug", "activate more debug messages. Can be set by env var DEBUG.", false)
  .parse(process.argv);

console.log(cli.debug)

и я получаю эту ошибку:

example.ts(3,32): error TS2503: Cannot find namespace 'commander'.

Насколько я понимаю, cli на самом деле является классом типа commander.Command Поэтому я попытался добавить класс:

import * as program from "commander";

class Cli extends program.Command {
    public debug: boolean;
}

const cli: Cli = program
  .version("1.0.0")
  .usage("[options]")
  .option("-d, --debug", "activate more debug messages. Can be set by env var DEBUG.", false)
  .parse(process.argv);

console.log(cli.debug)

Что дает мне эту ошибку:

example.ts(7,7): error TS2322: Type 'Command' is not assignable to type 'Cli'.
  Property 'debug' is missing in type 'Command'.

Я не знаю, как добавить свойство в класс Command ни в свой файл, ни в новый файл .d.ts.


person Louis Roché    schedule 05.05.2017    source источник


Ответы (2)


С вашим первым фрагментом кода и следующими зависимостями я не получаю ошибку:

"dependencies": {
    "commander": "^2.11.0"
},
"devDependencies": {
  "@types/commander": "^2.9.1",
  "typescript": "^2.4.1"
}

Typescript интерпретирует cli.debug как any. Я предполагаю, что объявления типов были обновлены. Итак, если у вас все в порядке с any, проблема решена.

Если вы действительно хотите сообщить Typescript тип debug, слияние объявлений в принципе был бы выход. В основном это работает так:

class C {
    public foo: number;
}

interface C {
    bar: number;
}

const c = new C();
const fooBar = c.foo + c.bar;

Однако есть проблема: program.Command — это не тип, а переменная. Итак, вы не можете сделать это:

interface program.Command {
    debug: boolean;
}

И пока вы можете сделать это:

function f1(): typeof program.Command {
    return program.Command;
}

type T = typeof program.Command;

function f2(): T {
    return program.Command;
}

Вы также не можете сделать это:

interface typeof program.Command {
}

Ни это:

type T = typeof program.Command;

interface T {
}

Я не знаю, можно ли решить эту проблему или нет.

person Marco Eckstein    schedule 08.07.2017

Я думаю, что нашел решение, я действительно не знаю, хорошая ли это практика, но тем не менее.

import { Command } from 'commander';
const cli = new Command();

interface InterfaceCLI{
  debug?: boolean;
}

cli
  .version("1.0.0")
  .usage("[options]")
  .option("-d, --debug", "activate more debug messages. Can be set by env var DEBUG.", false)
  .parse(process.argv);

const { debug } : InterfaceCli = <InterfaceCli><unknown>cli;
console.log(debug) // here debug is your cli.debug, I just used object destructuring

В строке перед последней я использую приведение типов, я первый приведение к unkown для непересекающихся типов, а затем, наконец, приведение к нашему интерфейсу — InterfaceCli.

person Kedel Mihail    schedule 24.03.2020