首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Typesafe嵌套属性查找

Typesafe嵌套属性查找
EN

Stack Overflow用户
提问于 2019-03-15 15:20:17
回答 3查看 2.8K关注 0票数 0

我正在尝试创建一个类型安全版本的get存档函数(参见这里)。我的想法是创建一个函数,如果嵌套的属性可用,则它能够返回正确的类型。

代码语言:javascript
复制
interface Nested {
  value: 'some' | 'type';
}
interface SomeComplexType {
  foo: string;
  bar: number;
  nested: Nested;
}

const testObject: SomeComplexType = {
  foo: 'foo value',
  bar: 1234,
  nested: {
    value: 'type'
  }
};

// The type of someValue should be: 'some' | 'type'
const someValue = lookup(testObject, 'nested.value');
console.log('Value found:', someValue);

现在我有以下几点:

代码语言:javascript
复制
function get<T, K extends keyof T>(object: T, key: K): T[K] | undefined {
  return object[key];
}

function lookup<T, K extends keyof T>(object: T, path: string) {
  const parts = path.split('.');
  const property = parts.shift() as K; // TODO autoinfer is possible?
  const value = get(object, property);

  if (!parts.length || value === undefined) {
    return value;
  }

  const newPath = parts.join('.');
  return lookup(value, newPath);
}

但是我还是被查找返回类型卡住了。严格模式下的打字稿写着:

src/lookup.ts:14:10 -错误TS7023:'lookup‘隐式具有返回类型'any’,因为它没有返回类型注释,并且在其返回表达式中直接或间接引用。

有什么想法吗?

EN

回答 3

Stack Overflow用户

发布于 2019-03-15 15:52:36

不幸的是,你想要做的事情超出了打字稿的能力,至少在这篇文章中是这样。主要问题是:

  1. TypeScript将无法弄清楚您到底要用该字符串做什么。TypeScript可以检查给定的字符串文本是否与对象的键匹配,但除此之外,它无法提供帮助。所以我们不能修复你的as K; // TODO autoinfer is possible?评论
  2. 您获得TS7023是因为您正在递归到对象中,而且由于我们可以在任何地方递归到对象中,所以TypeScript不确定要在哪里停止,因此它不得不推断返回类型为any

为了解决上面的第二个问题,我们可以尝试将函数声明更改为:

代码语言:javascript
复制
function lookup<T, K extends keyof T>(object: T, path: string): T[K] | undefined {

但是,TypeScript将在返回语句中抛出TS2322: Type 'T[K][keyof T[K]] | undefined' is not assignable to type 'T[K] | undefined'。本质上,TypeScript是在说“嵌套的子类型与父类型不一样,所以您编写的内容是错误的”。

尽管如此,在您尝试之前,还有一些已经相当接近了,不过据我所知,还没有一个完美的实现。在这个GitHub问题中,您可以阅读一些不同的解决方案:https://github.com/Microsoft/TypeScript/issues/12290 --其中大多数使用数组而不是字符串,因为TypeScript可以更容易地查看各个片段。

撇开

我想说的是,在TypeScript的世界里,你想要解决的问题是不太合理的。如果您对要访问的对象有了明确的定义--直接访问它就可以了!不需要额外的间接引导。TypeScript将键入-检查访问对象的方式。

如果需要在稍后动态返回特定字段,可以在某个地方创建一个匿名函数,并在稍后调用它,TypeScript可以键入-检查您的匿名函数。

如果您确实需要对没有类型的随机对象进行基于字符串的动态访问,那么any实际上是lookup函数的正确返回类型。因为如果您的代码没有明确的类型保证,那么它很可能是任何东西。

票数 3
EN

Stack Overflow用户

发布于 2019-06-18 19:04:31

我尝试了一些不同的想法,包括:https://github.com/pimterry/typesafe-get和我想我可以分享我自己对这个问题的看法。

我不使用字符串,而是使用封装在try/catch中的箭头函数来解析回退。通过这种方式,我可以查找访问器参数和返回类型,并有机会提供自己的回退:

代码语言:javascript
复制
type CallbackFn<T extends any[] = [], R extends any = void> = (...args: T) => R;

const get = <T extends any, R extends any, F extends any = null>(obj: T, accessor: CallbackFn<[T], R>, fallback: F = null): R | F => {
  if (!obj || typeof accessor !== 'function') {
    return fallback;
  }

  try {
    return accessor(obj);
  } catch (e) {
    return fallback;
  }
};

为此添加了git和更多详细信息:https://github.com/jan-rycko/get-by-accessor

票数 1
EN

Stack Overflow用户

发布于 2019-03-15 15:50:32

使您的函数成为可能的关键似乎是TypeScript应用类型查找操作(T[K])任意次数来解析T[K][U][V]之类的类型。这需要编译器能够执行代码本身( la 预置)。我只是觉得目前这是不可能的。我认为您可能需要手动调用适当数量的get函数来提取所需的类型。例如,这里的out类型是预期的'some' | 'type'

代码语言:javascript
复制
const out = get(get(testObject, 'nested'), 'value');

操场链接

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55185753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档