首页 > 解决方案 > [Typescript]:如何键入通用函数以接受更具体的对象作为参数?

问题描述

我想通过选择器属性将选择器传递给子组件。selector 属性是一个通用函数,它接受单个对象并返回一个值。请参见下面的示例(操场)。

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} />
};

它无法将具有特定属性的对象分配给接受任何属性的对象。这是为什么?我在不同的情况下遇到了这种情况,找不到解决方法。

(显然,我试图理解这个问题,而简单地关闭这些警告并不是一个理想的解决方案。)

标签: reactjstypescriptredux

解决方案


您可以使组件通用:

// 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} />
};

推荐阅读