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



假设我们需要实现一个返回一些东西的方法,但当这个东西是undefined时,它应该返回一些传入的默认值。但我们不想让默认值param成为必需的,所以我们将其声明为可选值:

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

因此,如果我理解正确,这对于泛型类型来说很容易:

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

查看操场

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分配类型。相反,您应该进行运行时检查(typescript从检查中推断类型(:

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

关于这个错误,我已经提交了一个问题。

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问题。

最新更新