如果 {} 允许任何非空值,为什么 `FC<{}>` 不允许任何属性?

问题描述 投票:0回答:2

我在 React TypeScript Cheatsheet 网站上看到了以下观点:“空接口、{} 和 Object 都代表“任何非空值”,而不是您可能认为的“空对象”。”

例如:

let value: {};

value = 1;
value = "foo";
value = () => alert("foo");
value = {};
value = { foo: "bar" };

value = undefined; // Error Type
value = null;  // Error Type

上面的示例表明,当类型为 {} 时,可以匹配字符串、函数和任何非空值。

所以,如下面的代码所示,当我将 Child 组件的类型定义为 FC<{}> 时,我的 props 类型变成了 {},这似乎意味着:“你可以将字符串、函数和任何非空值传递为给孩子的道具。”

但是,当我在父组件中使用 Child 组件并尝试将 Child 的 props 设置为 { id: '1111' } 时,会抛出错误。

const Child:FC<{}> = (props) => {
  return (
    <div>
      Child
    </div>
  )
}

const App = () => {
  return (
    {/**Error: Type '{ id: string; }' is not assignable to type 'IntrinsicAttributes'.**/}
    <Child id={'111'}/>
  );
}

但是,下面的代码可以正常工作。

let props: {}
props = {id: '111'}

我想得到一个基本的解释。

javascript reactjs typescript types interface
2个回答
0
投票

当您使用

FC<{}>
定义 React 组件时,您是在说该组件根本不接受任何 props。这是因为
{}
被解释为 props 对象不能包含任何键。所以
{}
意味着没有钥匙。

类型

{}
表示props对象是一个空对象。当您尝试传递
{ id: '111' }
时,TypeScript 会引发错误,因为
id
不是
{}
允许的键,因为
{}
应该根本没有键!

如果您希望

Child
组件接受任何道具,请按以下步骤操作:

const Child: FC<Record<string, unknown>> = (props) => {
  return (
    <div>
      Child
    </div>
  );
}

Record<string, unknown>
是一种 TypeScript 实用程序类型,表示具有任何类型的字符串键和值的对象。相当于
{ [key: string]: unknown }
unknown
指定值可以是任何类型,但它们的确切类型在编译时未知。

或者如果您希望孩子接受

id
作为道具:

const Child: FC<{ id: string }> = ({ id }) => {
  return (
    <div>
      Child with ID: {id}
    </div>
  );
}

0
投票

注意事项:

  1. React 功能组件就是函数
  2. React 中的函数是逆变的

引自博客:

逆变是一种规则,强制函数的输入类型 必须是其所在函数的输入类型的超类型 分配给

由于 TypeScript 的上述属性:

下面的代码编译时会出现错误:

type EmptyObject = {};

type Func = (f : EmptyObject) => void;

const func : Func = ({ id }) => {
console.log({id})
};

并且这个可以正常工作:

type IdObject = { id : string}

type Func2 = (f : IdObject) => void;


const func2 : Func2 = ({}) => {
};

这正是您在上面看到的行为。

游乐场

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.