如果参数未定义,则键入返回undefined的函数

时间:2017-01-19 16:27:23

标签: javascript flowtype

我们说我有这个功能(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)

我想以某种方式输入它,所以:

  • 如果参数为Just Person,则返回类型为Just String
  • 如果参数为Maybe person,则返回类型为Maybe String

这可能吗?

2 个答案:

答案 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)

这根据?ThingThing还是id正确返回number?number。目前,它仅处理一个额外的参数,但是可能会扩展为包含更多参数。