如何在Typescript中编写递归的不可空类型?

如何在Typescript中编写递归的不可空类型?,typescript,Typescript,我希望创建一个类似于但类型化的函数 以下是我目前掌握的情况: 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: {

我希望创建一个类似于但类型化的函数

以下是我目前掌握的情况:

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)
函数safeGet(主题:T,选择:(T:nonnull)=>R:R |未定义{
尝试{返回选择(主题);}
catch{return undefined;}
}
//示例使用
接口MyType{
someKey:{
someValue:字符串|未定义;
}|未定义
}
例如subject:MyType=/*…*/;
const gotSomeValue=safeGet(例如subject,s=>s.someKey.someValue)
这种方法可以工作,但不会递归地删除未定义的内容。有没有办法创建某种递归的
不可为空的
类型?

常量RNN_ORIG=Symbol();
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)
类型RecursiveNonNullable1={[K in keyof T]:RecursiveNonNullable}; 类型RecursiveNonNullable=RecursiveNonNullable1&{[RNN_ORIG]:T}; 函数safeGet (主题:T,选择:(T:recursivenonnull)=>R:R[typeof RNN_ORIG]|未定义{ 尝试{返回选择(主题);} catch{return undefined;} } //示例使用 接口MyType{ someKey:{ someValue:字符串|未定义; }|未定义 } 声明let exampleSubject:MyType; const gotSomeValue=safeGet(例如subject,s=>s.someKey.someValue)
谢谢你的纯魔法。这肯定回答了我最初的问题(因此我将其标记为已接受)但是我上面写的
safeGet
函数现在有一个问题,因为返回类型是
R | undefined
函数的结果是
RecursiveNonNullable1 | undefined
的一个版本,它应该是嵌套原始对象的嵌套原始类型。你有什么想法使它成为原来的类型吗?更新了答案。如果你遇到问题,请告诉我,我会看看是否能解决。