微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检查打字稿中的深点符号路径

如何解决检查打字稿中的深点符号路径

Typescript挑战(来自更复杂代码的简化示例)...拆分深对象路径并键入检查原始字符串。

在打字稿中有可能吗?还是我必须编写运行时检查?

代码注释中的更多详细信息

interface Residence {
  address: string;
  year: number;
  owner: {
    name: string;
  }
}

const house: Residence = {
  address: 'Type street 1',year: 2010,owner: {
    name: 'John Smith',},};

function getProp<T,K extends keyof T>(obj: T,key: K): T[K] {
  return obj[key];
}

// The following lines work as expected,including giving type errors for non-existing keys:
getProp(house,'address');
getProp(house,'year');
// @ts-expect-error: As expected,since 'other' is not part of Residence
getProp(house,'other');

function deeper<T,P>(obj: T,path: P) {
  // The logic here would be different,the point is splitting up the path
  // to be able to check each part towards the deeper structure of the object
  const firstProp = path.split('.')[0];
  getProp(obj,firstProp);
}

// The problem is when combining flat keys with deep paths. Is the following possible,including type errors for the nonexisting paths?
deeper(house,'address');
deeper(house,'owner');
deeper(house,'owner.name'); // Should work since the deep path exists in the type

// @ts-expect-error: Property 'city' is not in Residence
deeper(house,'city');
// @ts-expect-error: Deep path owner.email is not in Residence
deeper(house,'owner.email');

解决方法

使用 TypeScript 4.1,您确实几乎可以使用模板文字类型来实现这一点

type NestedValueOf<Obj,Key extends string> =
  Obj extends object ?
    Key extends `${infer Parent}.${infer Leaf}` ?
      Parent extends keyof Obj ?
        NestedValueOf<Obj[Parent],Leaf>
      : never
    : Key extends keyof Obj ? Obj[Key] : never
  : never

用法:

interface Residence {
  address: string;
  year: number;
  owner: {
    name: string;
  }
}

const house: Residence = {
  address: 'Type street 1',year: 2010,owner: {
    name: 'John Smith',},}

function getProp<T,Key extends string>(obj: T,key: Key): NestedValueOf<T,Key> {
  // TODO
}
getProp(house,'address')    // string
getProp(house,'owner')      // { name: string }
getProp(house,'owner.name') // string
getProp(house,'city')       // never

此版本中未对 keygetProp 参数进行类型检查。 This answer 可能对此有所帮助

,

恐怕您不能完全做到这一点,您必须传递字符串数组,这是我们键入lodash get的范例。 (可能不是最漂亮的,但它可以工作,我们不再需要新的打字稿功能(例如新的字体保护程序和可选的链接)使用它

您要查找的结果是什么,如果需要检查对象是否来自联合,则应使用typeguards:https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

import _ from 'lodash';
export interface TypedExtractor {
    <T,K1 extends keyof T>(object: T,key1: K1): T[K1];
    <T,K1 extends keyof T,K2 extends keyof T[K1]>(object: T,key1: K1,key2: K2): T[K1][K2];
    <T,K2 extends keyof T[K1],K3 extends keyof T[K1][K2]>(object: T,key2: K2,key3: K3): T[K1][K2][K3];
    <T,K3 extends keyof T[K1][K2],K4 extends keyof T[K1][K2][K3]>(
        object: T,key3: K3,key4: K4,): T[K1][K2][K3][K4];
    <
        T,K4 extends keyof T[K1][K2][K3],K5 extends keyof T[K1][K2][K3][K4]
    >(
        object: T,key5: K5,): T[K1][K2][K3][K4][K5];
    <
        T,K5 extends keyof T[K1][K2][K3][K4],K6 extends keyof T[K1][K2][K3][K4][K5]
    >(
        object: T,key6: K6,): T[K1][K2][K3][K4][K5][K6];
    <
        T,K6 extends keyof T[K1][K2][K3][K4][K5],K7 extends keyof T[K1][K2][K3][K4][K5][K6]
    >(
        object: T,key7: K7,): T[K1][K2][K3][K4][K5][K6][K7];
    <
        T,K7 extends keyof T[K1][K2][K3][K4][K5][K6],K8 extends keyof T[K1][K2][K3][K4][K5][K6][K7]
    >(
        object: T,key8: K8,): T[K1][K2][K3][K4][K5][K6][K7][K8];
    <
        T,K8 extends keyof T[K1][K2][K3][K4][K5][K6][K7],K9 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8]
    >(
        object: T,key9: K9,): T[K1][K2][K3][K4][K5][K6][K7][K8][K9];
    <
        T,K9 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8],K10 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8][K9]
    >(
        object: T,key10: K10,): T[K1][K2][K3][K4][K5][K6][K7][K8][K9][K10];
}

export const _get: TypedExtractor = (object: any,...keys: (string | number)[]): string | number | object | undefined => {
    return _.get(object,keys);
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?