简体   繁体   English

为什么 TypeScript 在将 object 文字分配给扩展 object 文字的泛型类型时会抱怨?

[英]Why TypeScript complains when assigning an object literal to a generic type extending object literals?

I don't understand why the TypeScript compiler is complaining about this code:我不明白为什么 TypeScript 编译器抱怨这段代码:

import { useState, useEffect } from 'react';

function useSomething<T extends { [key: string]: any }>(): T {
  const [state, setState] = useState<T>({});  // Argument of type '{}' is not assignable to parameter of type 'T | (() => T)'.

  useEffect(() => {
    setState({ hello: 'world' });
  });

  return state;
}

Since basically, this code works: const t: { [key: string]: any } = { hello: 'world' } .因为基本上,这段代码有效: const t: { [key: string]: any } = { hello: 'world' }

Example playground: https://www.typescriptlang.org/play/?ssl=14&ssc=36&pln=14&pc=52#code/JYWwDg9gTgLgBAbzgVwM4FMDKMCGN0A0KGAogGZnoDG8AvnGVBCHAORTo42sDcAUHzLIAdjWARhxLM3QwAFsGEBzADwAVOOgAe+YQBNUiOAG0A1ugCeALjioYURUoC6NnMItxaAPgAUAShsNBD44OCoJOxM7PEJbWWwYpzgAXikE-HVfBFo-fhCpckoaH38Ur0R80IwYdPQfJDl0ABsmiBtWAHdoJr1WT1z8nLzQjhhkKElo-H5aAT5w4UiYGyQzSxs7B2UXODcPelTs-gWlgCYVk3NrW3tHHb3PFKNGlra2LqgevtoeIA Example playground: https://www.typescriptlang.org/play/?ssl=14&ssc=36&pln=14&pc=52#code/JYWwDg9gTgLgBAbzgVwM4FMDKMCGN0A0KGAogGZnoDG8AvnGVBCHAORTo42sDcAUHzLIAdjWARhxLM3QwAFsGEBzADwAVOOgAe+YQBNUiOAG0A1ugCeALjioYURUoC6NnMItxaAPgAUAShsNBD44OCoJOxM7PEJbWWwYpzgAXikE-HVfBFo-fhCpckoaH38Ur0R80IwYdPQfJDl0ABsmiBtWAHdoJr1WT1z8nLzQjhhkKElo-H5aAT5w4UiYGyQzSxs7B2UXODcPelTs-gWlgCYVk3NrW3tHHb3PFKNGlra2LqgevtoeIA

EDIT : A better example, the question is basically, is it possible to type this in TypeScript?编辑:一个更好的例子,问题基本上是,是否可以在 TypeScript 中输入这个?

import { useState } from 'react';

function useComplexState<T extends Record<string, any>>() {
  const [state, setState] = useState<T>({});

  const setter = (key: keyof T, value: any) => {
    setState((state) => ({ ...state, [key]: value }));
    return state;
  };

  const getter = (key: keyof T) => {
    return state[key];
  }

  return { set: setter, get: getter };
}

interface Person {
  firstName: string;
  lastName: string;
}

const personState = useComplexState<Person>();

personState.get('firstName');
personState.set('lastName', 'Smith');

A few comments about the code:关于代码的一些评论:

  • I want T to always be an object {} so no one should be able to do useComplexState<boolean>我希望T始终是 object {}所以没有人应该能够做useComplexState<boolean>
  • Ideally, T shouldn't be required, so if I use useComplexState() I should just have a generic object Record<string, any> inside.理想情况下,不需要T ,所以如果我使用useComplexState()我应该只有一个通用的 object Record<string, any>里面。
  • I'd like to have a default value of {} for the state .我想为state设置一个默认值{}

Adding as T in useState<T>({} as T) fixed every issue.useState<T>({} as T)中添加as T修复了每个问题。

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

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