Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 如何将模板文字类型用于强类型;获取属性路径“;功能_Typescript - Fatal编程技术网

Typescript 如何将模板文字类型用于强类型;获取属性路径“;功能

Typescript 如何将模板文字类型用于强类型;获取属性路径“;功能,typescript,Typescript,我正在玩弄模板文字类型,试图让我的头脑包围它们,但我不太明白我希望这是一个简单的练习:一个强类型函数,其中get(obj,'foo.bar.baz')返回obj.foo.bar.baz的类型。(这是一个垫脚石,能够以某种方式强力键入我的作品的自制验证程序+消毒剂库,该库使用点分隔路径来指示嵌套属性 我的第一个方法是: type GetResult<Value, Path> = Path extends `${infer Pre}.${infer Post}` ? (Value

我正在玩弄模板文字类型,试图让我的头脑包围它们,但我不太明白我希望这是一个简单的练习:一个强类型函数,其中
get(obj,'foo.bar.baz')
返回
obj.foo.bar.baz
的类型。(这是一个垫脚石,能够以某种方式强力键入我的作品的自制验证程序+消毒剂库,该库使用点分隔路径来指示嵌套属性

我的第一个方法是:

type GetResult<Value, Path> = Path extends `${infer Pre}.${infer Post}` 
  ? (Value extends {Pre: infer InnerValue} ? GetResult<InnerValue, Post> : undefined) 
  : (Value extends {Path: infer Result} ? Result : undefined);

function get<V, P>(val: V, path: P): GetResult<V, P> {
  // @ts-ignore
  return;
}

const val = {
  foo: {
    bar: {
      quux: 123
    }
  }
}

const quux = get(val, 'foo');

我在这里哪里出错了?

您的问题是类型
{Pre:any}
有一个带有文本字符串值的键
“Pre”
;它不是一个带有
Pre
类型键的字符串。表示您需要一个类似
{[K in Pre]:any}的字符串
或等效的
记录
。如果你解决了这个问题,我想你会取得一些进展


现在,突然出现标题中的问题,即

如何为强类型“get property path”函数使用模板文字类型

我给使用虚线路径的“深度索引”函数打字的方式可能如下所示:

type DeepIndex<T, K extends string> = T extends object ? (
  string extends K ? never :
  K extends keyof T ? T[K] :
  K extends `${infer F}.${infer R}` ? (F extends keyof T ?
    DeepIndex<T[F], R> : never
  ) : never
) : never

type ValidatePath<T, K> =
  K extends string ? DeepIndex<T, K> extends never ? never : K : never;

declare const get: <T, K extends string>(
  object: T,
  keyName: K & ValidatePath<T, K>
) => DeepIndex<T, K>;
我肯定有一些边缘情况。例如,如果你的任何属性的名称中有一个
”,那你就倒霉了。我希望像
{“foo.bar”:{“baz.quox”:123}
这样的东西在这里做非常糟糕的事情。但至少它表明了一般的方法,一个在
处拆分字符串的递归类型函数
字符,可以工作


simpleGet
在您提供的示例中返回未定义的,这可能是issue@BooklynDadCore是的,我知道。为什么它会返回它,而不是
val.foo
的类型?在这个示例中,函数没有逻辑,只有一个返回。哦,天哪,你是对的,被语法高亮显示匹配它们愚弄了
type DeepIndex<T, K extends string> = T extends object ? (
  string extends K ? never :
  K extends keyof T ? T[K] :
  K extends `${infer F}.${infer R}` ? (F extends keyof T ?
    DeepIndex<T[F], R> : never
  ) : never
) : never

type ValidatePath<T, K> =
  K extends string ? DeepIndex<T, K> extends never ? never : K : never;

declare const get: <T, K extends string>(
  object: T,
  keyName: K & ValidatePath<T, K>
) => DeepIndex<T, K>;
const val = {
  foo: {
    bar: {
      quux: 123
    }
  }
}
    
const barQuuxNumber = get(val, 'foo'); // {bar: {quux: number}};
const num = get(val, 'foo.bar.quux'); // number