简体   繁体   English

[Typescript]:如何键入通用 function 以接受更具体的 object 作为参数?

[英][Typescript]: How to type a generic function to accept a more specific object as argument?

I want to pass a selector to a child component via selector property.我想通过选择器属性将选择器传递给子组件。 The selector property is a generic function which accepts a single object and returns a value. selector 属性是一个通用的 function ,它接受单个 object 并返回一个值。 See example below ( playground ).请参见下面的示例( 操场)。

import React from 'react';

// Some simple state
type State = {
  user: {
    name: string,
    surname: string,
  }
};

// Some simple selector
const getUserName = (state: State) => state.user.name;

type Selector = <RootState = Record<string, unknown>, Selected = unknown>(state: RootState) => Selected;

// React Component Properties
type Properties = {
  selector: Selector;
};

// Component
const Component = (props: Properties) => {
  const { selector } = props;

  /** Do something with the selector */

  return null;
};

// Parent component passing a selector to child
const App = () => {
//   Type '(state: State) => string' is not assignable to type '<RootState = {}, Selected = unknown>(state: RootState) => Selected'.
//   Types of parameters 'state' and 'state' are incompatible.
//     Type 'RootState' is not assignable to type 'State'.(2322)
// input.tsx(16, 3): The expected type comes from property 'selector' which is declared here on type 'IntrinsicAttributes & Properties'
  return <Component selector={getUserName} />
};

It fails to assign an object with specific properties into an object which accepts any properties.它无法将具有特定属性的 object 分配给接受任何属性的 object。 Why is that?这是为什么? I encountered this in a different situation and couldn't find a workaround.我在不同的情况下遇到了这种情况,找不到解决方法。

(Obviously, I am trying to understand the issue and simply turning these warnings off is not a desired solution.) (显然,我试图理解这个问题,而简单地关闭这些警告并不是一个理想的解决方案。)

You can make the component generic:您可以使组件通用:

// React Component Properties
type Properties<RootState extends Record<string, unknown>, Selected> = {
  selector: (state: RootState) => Selected;
};

// Component
function Component<RootState extends Record<string, unknown>, Selected>(props: Properties<RootState, Selected>) {
  const { selector } = props;

  /** Do something with the selector */

  return null;
}

// Parent component passing a selector to child
const App = () => {
  return <Component selector={getUserName} />
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM