我们说我有这个功能(try online):
type Person = { name: string }
function getName(p: ?Person): ?string {
if (!p) {
return p
} else {
return p.name
}
}
const frank: Person = { name: 'Frank' }
/*
* In order to work now, this has to have a maybe type
* const name: ?string = getName(frank)
* Even though I know it will is guaranteed to be a string
*/
const name: string = getName(frank)
我收到错误,因为Flow认为getName
可以返回undefined
。虽然只会发生这种情况,但如果p
未定义,则情况并非如此。
我能否以某种方式输入函数,返回类型为undefined
仅当参数为undefined
时,否则为字符串?
编辑:
澄清示例: 我有一个简单的功能:
function getName(person) {
if (! person) {
return undefined
} else {
return person.name
}
}
const maybeFrank: ?Person = getFrank()
const definitelyMaria: Person = getMaria()
const frankName: ?string = getName(maybeFrank)
const mariaName: string = getName(definitelyMaria)
我想以某种方式输入它,所以:
这可能吗?
答案 0 :(得分:3)
我的意见是从函数参数中删除?
并将消除歧义留给调用站点。 e.g。
type Person = { name: string }
function getName(person: Person): string {
return person.name
}
const maybeFrank: ?Person = Math.random() > 0.5 ? {name: 'Frank'} : undefined;
const definitelyMaria: Person = {name: 'Maria'};
const frankName: ?string = maybeFrank && getName(maybeFrank)
const mariaName: string = getName(definitelyMaria);
否则,如果您真的想要,可以使用显式类型
明确重新声明该函数type Person = { name: string }
declare function getName(p: Person): string;
declare function getName(p: void): void;
function getName(p: ?Person): ?string {
if (!p) {
return undefined
} else {
return p.name
}
}
const frank: Person = { name: 'Frank' }
const name: string = getName(frank)
答案 1 :(得分:0)
我喜欢@loganfsmyth的解决方案,但发现它涉及到每个选择器太多的输入。
我想出了一种使它更通用的方法,它使您不必为每个选择器创建多个类型签名。
type FinderT<A, B, C> = (A, B) => C
declare function maybe<B, C>(cb: FinderT<number, B, C>, id: number, other: B): C
declare function maybe<B, C>(cb: FinderT<number, B, C>, id: ?number, other: B): void // eslint-disable-line no-redeclare
export function maybe(cb, id, other) { // eslint-disable-line no-redeclare
if (!id) {
return undefined
} else {
return cb(id, other)
}
}
用法:
maybe(findPerson, 42, state)
这根据?Thing
是Thing
还是id
正确返回number
或?number
。目前,它仅处理一个额外的参数,但是可能会扩展为包含更多参数。