简体   繁体   English

如何在 Typescript 中使用联合类型返回值?

[英]How to use union type return value in Typescript?

I am trying to use shelljs (via DefinitelyTyped ) in Typescript 1.5-beta.我正在尝试在 Typescript 1.5-beta 中使用shelljs (通过绝对类型)。 In my code I would like to use the exec function which has the following signature:在我的代码中,我想使用具有以下签名的exec函数:

export function exec(command: string, options: ExecOptions): ExecOutputReturnValue | child.ChildProcess;

export interface ExecOutputReturnValue
{
    code: number;
    output: string;
}

If I import and use the library as follows (which, in normal ES6 JavaScript works perfectly fine)如果我按如下方式导入和使用该库(这在正常的 ES6 JavaScript 中工作得很好)

import * as $ from 'shelljs';
const code =  $.exec(command, { silent: true }).code;

the Typescript compiler gives me error TS2339: Property 'code' does not exist on type 'ChildProcess | ExecOutputReturnValue' Typescript 编译器给了我error TS2339: Property 'code' does not exist on type 'ChildProcess | ExecOutputReturnValue' error TS2339: Property 'code' does not exist on type 'ChildProcess | ExecOutputReturnValue' . error TS2339: Property 'code' does not exist on type 'ChildProcess | ExecOutputReturnValue'

What can I do to access .code in a type-safe way?我该怎么做才能以类型安全的方式访问 .code?

When you have a union type, you will see any shared members when you use it raw.当你有一个联合类型时,当你使用它时你会看到任何共享的成员。

If you want to use more specific members, you need to use a type guard.如果要使用更具体的成员,则需要使用类型保护。 Inside of the type guard, you will have access to all of the specific members for the type.在类型保护内部,您将可以访问该类型的所有特定成员。

Here is a cut down example:这是一个缩减示例:

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.
}

When you are dealing with types that you can't apply a typeof check, you'll need to tell the compiler that "you know best":当您处理无法应用typeof检查的类型时,您需要告诉编译器“您最了解”:

const code =  (<ExecOutputReturnValue >$.exec(command, { silent: true })).code;

This is an old question, but if anyone comes across it, this may help.这是一个老问题,但如果有人遇到它,这可能会有所帮助。 In newer versions of TS, using user-defined type guards with type predicates is safer than simply "telling the compiler you know best" and can help avoid runtime errors in cases where you think you know best but actually don't :-).在较新版本的 TS 中,使用带有类型谓词的用户定义类型保护比简单地“告诉编译器您最了解”更安全,并且可以帮助避免在您认为自己最了解但实际上并不了解的情况下的运行时错误:-)。

Using the OPs example:使用 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
}

The key to making this work is the isExecOutput function's return type: code is ExecOutputReturnValue .完成这项工作的关键是isExecOutput函数的返回类型: code is ExecOutputReturnValue Called a type predicate, which makes user-defined type guards like these possible.称为类型谓词,这使得像这样的用户定义类型保护成为可能。 The official documentation can be found here .官方文档可以在这里找到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM