返回类型的加强取决于是否传递了可选参数

时间:2018-12-07 21:47:23

标签: typescript

假设我们需要实现一个返回值的方法,但是当该值是undefined时,它应该返回一些传入的默认值。但是我们不想将默认值参数设为必需,因此将其声明为可选参数:

private returnSomething(someParam: string, defaultValue?: string) : string | undefined {
    const result: string | undefined = ...; // Some result-producing logic
    return result !== undefined ? result : defaultValue;
}

我们希望以下内容可以在严格模式下编译(注意,something1: string类型声明为没有undefined部分):

const something1: string = this.returnSomething("someParam1", "?"); // Error, no undefined in the type of something1
const something2: string | undefined = this.returnSomething("someParam2");

是否可以在TypeScript中声明一个方法,以便当不传递可选参数时,该方法的返回类型被视为string | undefined,而在传递该参数时,返回类型变为string

2 个答案:

答案 0 :(得分:2)

因此,如果我正确理解了您,只需使用generic类型,即可轻松实现:

const returnSomething = <D extends string | undefined>(someParam: string, defaultValue?: D) : D extends undefined ? string | undefined : string => {

  const result = {} as any;

  return result !== undefined ? result : defaultValue;
}

请参见playground

UPD以避免在不使用any的情况下出错:

const returnSomething = <D extends string | undefined, R extends D extends undefined ? string | undefined : string>(someParam: string, defaultValue?: D) : R => {

  const result = 'str';

  return (result !== undefined ? result : defaultValue) as R;
}

UPD2。正确的方法(以及对此的歉意)。

我想道歉,因为在不必要的时候,我介绍了泛型和条件类型。我的意思是,我不知道它们会导致这样的错误。但是我也被最初的问题所误导。 因此,通常的方式,我将如何实现,像这样:

const returnSomething = (someParam: string, defaultValue?: string): string | undefined => {

    const result = '';

    return result !== undefined ? result : defaultValue;
}

const something1 = returnSomething("someParam1", "?");
const something2 = returnSomething("someParam2");

就是这样。是的,您不应该为something1something2分配类型。相反,您应该进行运行时检查(并且打字稿从检查中推断出类型):

if (typeof something1 === 'undefined') { 
    /* oops the value is undefined, do something to make the program continue working properly */ 
} 
else {
    something1 // has type "string"
}

关于错误,我已经提交了issue

答案 1 :(得分:1)

Nurbol是其中的大部分方式,我必须进行另一处更改才能使其完全正常工作:

const returnSomething = <D extends string | undefined>(someParam: string, defaultValue?: D) : D extends undefined ? string | undefined : string => {
  const result = {} as any;
  return result !== undefined ? result : defaultValue;
}

const something1: string = returnSomething("someParam1", "d"); // No error
const something2: string | undefined = returnSomething("someParam2"); // No error
const something3: string = returnSomething("someParam2"); // Yes error
const something4: string = returnSomething("someParam2", undefined); // Yes error

我们需要定义D以便最初接受undefined,否则条件将始终仅返回string

尽管这样做的副作用是现在允许您将undefined作为默认值进行传递。仍然会出现预期的错误。

您也可以通过函数重载来做到这一点:

function returnSomething(param: string): string | undefined;
function returnSomething(param: string, defaultValue: string): string;
function returnSomething(param: string, defaultValue?: string) {
  const result = {} as any;
  return result !== undefined ? result: defaultValue;
}

这避免了undefined问题。