假设我们需要实现一个返回一些东西的方法,但当这个东西是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");
就是这样。是的,你不应该给something1
和something2
分配类型。相反,您应该进行运行时检查(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
问题。