这是Node.js控制台命令解析器arg的类型:
declare const flagSymbol: unique symbol;
declare function arg<T extends arg.Spec>(spec: T, options?: arg.Options): arg.Result<T>;
declare namespace arg {
export function flag<T>(fn: T): T & { [flagSymbol]: true };
export const COUNT: Handler<number> & { [flagSymbol]: true };
export type Handler <T = any> = (value: string, name: string, previousValue?: T) => T;
export interface Spec {
[key: string]: string | Handler | [Handler];
}
export type Result<T extends Spec> = { _: string[] } & {
[K in keyof T]?: T[K] extends Handler
? ReturnType<T[K]>
: T[K] extends [Handler]
? Array<ReturnType<T[K][0]>>
: never
};
export interface Options {
argv?: string[];
permissive?: boolean;
stopAtPositional?: boolean;
}
}
export = arg;
我需要注释解析结果:
import parseConsoleArgument from 'arg';
export function cli(rawConsoleCommandData: Array<string>): void {
const consoleCommandArguments: /* ??? */ = parseConsoleArgument(
{}, { argv: rawConsoleCommandData.slice(2)}
);
}
逻辑上正确的类型是arg.Result
。但是,我无法访问它。下面的代码
import parseConsoleArgument from 'arg';
export function cli(rawConsoleCommandData: Array<string>): void {
const consoleCommandArguments: arg.Result = parseConsoleArgument(
{}, { argv: rawConsoleCommandData.slice(2)}
);
}
给予TS2503: Cannot find namespace "arg"
。
答案 0 :(得分:1)
不确定为什么要注释变量,它将根据parseConsoleArgument
的结果来推断其类型。因此它将已经是适当的类型。如果您的团队要求在所有变量上都添加注释,则您应该挑战IMO,如果不复制大量代码,则很难注释很多类型。这是其中一种情况,让我们看看原因。
访问Result
并不是问题,您只是不通过arg
命名空间访问它,而是需要通过使用的模块别名来访问它:
const consoleCommandArguments: parseConsoleArgument.Result<{}> = parseConsoleArgument(
{}, { argv: rawConsoleCommandData.slice(2)}
);
这有效,但是您看到您使用了parseConsoleArgument.Result
的{{1}}的类型参数。在您开始添加要解析的参数之前,这似乎不是问题:
{}
如果我们删除显式注释,则不会出现错误,并且export function cli(rawConsoleCommandData: Array<string>): void {
const consoleCommandArguments: parseConsoleArgument.Result<{}> = parseConsoleArgument(
{ p: Number, p2: Boolean }, { argv: rawConsoleCommandData.slice(2)}
);
consoleCommandArguments.p // err
}
是一个p
,正如人们所期望的那样。发生这种情况是因为number
是一个通用函数,该函数从其第一个参数中提取类型信息,并使用条件类型来创建具有parseConsoleArgument
如果要手动键入此内容,则需要编写:
{ p: number, p2: Boolean }
哪个可以工作,但丑陋,并且比原来的长得多(不必要),并且要求我们更改两个位置以添加新参数。我会让编译器推断类型,这是相当不错的。任何想要查看实际类型的人都可以将鼠标悬停在变量上,他们会在工具提示中看到该类型