如何在Typescript中编写递归NonNullable类型?

时间:2018-08-28 18:11:47

标签: typescript

我正在寻求创建一个与lodash's get类似但被键入的函数。

这是我到目前为止所拥有的:

function safeGet<T, R>(subject: T, select: (t: NonNullable<T>) => R): R | undefined {
  try { return select(subject); }
  catch { return undefined; }
}

// example use
interface MyType {
  someKey: {
    someValue: string | undefined;
  } | undefined
}

let exampleSubject: MyType = /* ... */;

const gotSomeValue = safeGet(exampleSubject, s => s.someKey.someValue)

这种工作方式,但不会递归地删除未定义的内容。有没有办法创建某种递归NonNullable类型?

1 个答案:

答案 0 :(得分:1)

const RNN_ORIG = Symbol();
type RecursiveNonNullable1<T> = { [K in keyof T]: RecursiveNonNullable<T[K]> };
type RecursiveNonNullable<T> = RecursiveNonNullable1<NonNullable<T>> & {[RNN_ORIG]: T};

function safeGet<T, R extends { [RNN_ORIG]: unknown }>
  (subject: T, select: (t: RecursiveNonNullable<T>) => R): R[typeof RNN_ORIG] | undefined {
  try { return select(<any>subject); }
  catch { return undefined; }
}

// example use
interface MyType {
  someKey: {
    someValue: string | undefined;
  } | undefined
}

declare let exampleSubject: MyType;
const gotSomeValue = safeGet(exampleSubject, s => s.someKey.someValue)