我正在尝试在Typescript 1.5-beta中使用shelljs(通过DefinitelyTyped)。在我的代码中,我想使用具有以下签名的exec
函数:
export function exec(command: string, options: ExecOptions): ExecOutputReturnValue | child.ChildProcess;
export interface ExecOutputReturnValue
{
code: number;
output: string;
}
如果我按如下方式导入和使用该库(在正常的ES6 JavaScript中工作完全正常)
import * as $ from 'shelljs';
const code = $.exec(command, { silent: true }).code;
Typescript编译器给了我error TS2339: Property 'code' does not exist on type 'ChildProcess | ExecOutputReturnValue'
。
如何以类型安全的方式访问.code? p>
答案 0 :(得分:6)
当你有一个工会类型时,你会看到任何共享成员,当你原始使用它时。
如果您想使用更具体的成员,则需要使用类型保护。在类型防护装置内部,您可以访问该类型的所有特定成员。
这是一个减少的例子:
declare class Test {
example(): string | number;
}
var x = new Test();
var y = x.example();
if (typeof y === 'string') {
// In here, y has all the members of a string type
y.
} else {
// In here, y has all the members of a number type
y.
}
当您处理不能应用typeof
检查的类型时,您需要告诉编译器“您最了解”:
const code = (<ExecOutputReturnValue >$.exec(command, { silent: true })).code;
答案 1 :(得分:2)
这是一个古老的问题,但是如果有人遇到它,这可能会有所帮助。在更新版本的TS中,使用带有类型谓词的用户定义类型防护比简单地“告诉您最了解的编译器”更安全,并且可以避免在您认为自己最了解但实际上却确实发生运行时错误的情况别 :-)。
使用OP示例:
import * as $ from 'shelljs';
// our user-defined type guard, note the return type
const isExecOutput = (result: ExecOutputReturnValue | child.ChildProcess): code is ExecOutputReturnValue => {
return (result as ExecOutputReturnValue).code !== undefined;
}
const result: ExecOutputReturnValue | child.ChildProcess = $.exec(command, { silent: true });
if (isExecOutput(result)) {
doSomething(result.code); // safe!
} else {
// ... accessing the other type's members is safe here
}
完成这项工作的关键是isExecOutput
函数的返回类型:code is ExecOutputReturnValue
。称为类型谓词,这使像这样的用户定义类型防护成为可能。可以找到here的官方文档。