Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.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
Reactjs Typescript-从对象属性值推断泛型类型_Reactjs_Typescript - Fatal编程技术网

Reactjs Typescript-从对象属性值推断泛型类型

Reactjs Typescript-从对象属性值推断泛型类型,reactjs,typescript,Reactjs,Typescript,我读了很多书,发现了相似的东西,但并不完全是我想要的 我想通过在对象内使用prop值来定义类型,并使用该信息来定义该对象内的其他属性 intrinsiceelements包括所有react元素的定义。对于本例,让我们关注SVG元素圆圈和路径 因此,让我们尝试定义类型防御: 导出类型svgCustomType={ svgElem:T; svgProps?:{[key-in-keyof-JSX.intrinsiceelements[T]]:JSX.intrinsiceelements[T]}; };

我读了很多书,发现了相似的东西,但并不完全是我想要的

我想通过在对象内使用prop值来定义类型,并使用该信息来定义该对象内的其他属性

intrinsiceelements包括所有react元素的定义。对于本例,让我们关注SVG元素
圆圈
路径

因此,让我们尝试定义类型防御:

导出类型svgCustomType={
svgElem:T;
svgProps?:{[key-in-keyof-JSX.intrinsiceelements[T]]:JSX.intrinsiceelements[T]};
};
在这里,我尝试获取类型值T(可以是“路径”或“圆”),并使用此值定义
svgProps
(可以是
React.svgProps
React.svgProps

用法示例:

const测试:svgCustomType={//Error:“泛型类型'svgCustomType'需要1个类型参数”,为什么?
svgElem:“路径”,
svgProps:{
cx:10,//此处的下一步:应为错误,因为在`svgpatheElement'中未定义cx`
},
};
为什么获取
泛型类型“svgCustomType”需要1个类型参数
?我想从
svgElem
值获取此类型

我只想提到,使用
const-test:svgCustomType={…}
将起作用,而
cx
将不被接受

用于清楚地
我甚至不确定在typescript中是否可以使用它。
我正在写一篇文章,我希望我的用户能够在键入时获得IntelliSense建议,如果用户运行typescript(而不是javascript),他也会收到键入错误。
假设我的lib组件具有prop
svgHeadProp
类型
svgCustomType

因此,我希望用户能够编写:

svgHeadProp={svgElem:"path",svgProps:{...}}
而不是:

svgHeadProp<"path">={svgElem:"path",svgProps:{...}}
svgHeadProp={svgElem:“路径”,svgProps:{…}

因为不是所有我的用户都使用typescript(对于那些使用typescript的用户来说,为道具指定类型很烦人)问题是,要在类型签名中使用
SvgCustomTypeGeneric
,您必须传递该类型参数。使用
SvgCustomTypeGeneric
将不起作用,因为这将只允许
t
的每次出现都是
'path'
'circle'
,而它们之间没有任何依赖关系。但是,什么能起作用呢是一种联合类型,
SvgCustomTypeGeneric | SvgCustomTypeGeneric
,可以从
“路径”|“圆”
联合创建

为了说明它是如何工作的,让我们将泛型函数重命名为
SvgCustomTypeGeneric
,并使用
JSX.intrinsiceelements[T]
作为
svgProps
的类型(否则这些值是嵌套的,例如
svgProps:cx:{cx:10})

测试时,
cx
属性没有帮助,因为在
svgpatheElement
上也允许使用该属性,但是
ref
属性需要正确键入的值,可以使用该属性:

const test: SvgCustomType[] = [{
    svgElem: 'path',
    svgProps: {
      cx: 10, // No error, SVGPathElement can have 'cx' properties.
      ref: createRef<SVGPathElement>(),
    },
  }, {
    svgElem: 'circle',
    svgProps: {
      cx: 10,
      ref: createRef<SVGCircleElement>(),
    },
  }, { // ERROR
    svgElem: 'circle',
    svgProps: {
      cx: 10,
      ref: createRef<SVGPathElement>(),
    },
  },
]
如果你真的想全力以赴,你甚至可以放弃对SvgKey的依赖:

type SvgCustomTypeUltimate = 
  keyof JSX.IntrinsicElements extends infer T ? T extends keyof JSX.IntrinsicElements ? {
    svgElem: T;
    svgProps?: JSX.IntrinsicElements[T]
  } : never : never
这两种类型的行为与上面定义的
SvgCustomType
相同


有一个解决方案可以让类型匹配,但它不会在
cx
上给出错误,因为
会做出反应。SVGProps
确实有一个
cx
属性,原因是()。
svgCustomType
出现错误的原因是因为
SVGProps
键入,您需要使用
SVGProps:{cx:{cx:10}
,路径和圆都可以接受。)这是一个很好的答案!这就是我一直在寻找的!谢谢!不客气:-)关于一艘班轮,这是可能的,但并不漂亮。让我把它添加到答案中。伟大的更新朋友!但愿我能投两次赞成票!
const test: SvgCustomType[] = [{
    svgElem: 'path',
    svgProps: {
      cx: 10, // No error, SVGPathElement can have 'cx' properties.
      ref: createRef<SVGPathElement>(),
    },
  }, {
    svgElem: 'circle',
    svgProps: {
      cx: 10,
      ref: createRef<SVGCircleElement>(),
    },
  }, { // ERROR
    svgElem: 'circle',
    svgProps: {
      cx: 10,
      ref: createRef<SVGPathElement>(),
    },
  },
]
const mkSvg =<K extends SvgKey>(x: SvgCustomTypeGeneric<K>) => x

const test = mkSvg({
  svgElem: 'circle',
  svgProps: {
    ref: createRef<SVGPathElement>(),
    // Type 'RefObject<SVGPathElement>' is not assignable to type 'LegacyRef<SVGCircleElement> 
  },
})
export type SvgCustomTypeOneLiner =
  SvgKey extends infer T ? T extends SvgKey ? {
    svgElem: T;
    svgProps?: JSX.IntrinsicElements[T]
  } : never : never
type SvgCustomTypeUltimate = 
  keyof JSX.IntrinsicElements extends infer T ? T extends keyof JSX.IntrinsicElements ? {
    svgElem: T;
    svgProps?: JSX.IntrinsicElements[T]
  } : never : never