【问题标题】:Type 'unknown' is not assignable to type 'never'.ts(2322)类型“未知”不可分配给类型“从不”.ts(2322)
【发布时间】:2020-12-27 16:37:09
【问题描述】:

如果你想在浏览器中运行它,我创建一个Typescript Playground

我有类似的错误之前我能够修复,但这个错误似乎并不想消失。我确定这是一个打字问题,但不知道如何解决这个问题。

我查找了类似的情况,所有这些情况都建议您正确键入您正在处理的对象,在我的情况下是 task,我将其转换为 TaskInterface 类型。我将 replace.key 的参数输入为 keyof TaskInterface。不知道我还能做什么。

接口中的可选属性会不会是导致 typeof never 的原因?

接口

export interface PopulatableTaskInterface {
  columns?: unknown;
}
export interface TaskBase extends PopulatableTaskInterface {
  title: string;
  description?: string;
  participants?: Array<string>;
  deadline?: Date;
  taskIdentifier?: number;
  messageIds?: Types.Map<string>;
  guildId: mongoose.Types.ObjectId;
  completed?: boolean;
  createdTimestamp?: number;
  completedTimestamp?: number;
  wip?: boolean;
}
export interface TaskBaseInterface extends TaskBase, mongoose.Document {}

export interface TaskInterface extends TaskBaseInterface {
  columns: Types.Array<Schema.Types.ObjectId>;
}

功能

async edit(
    query: {
      key: keyof TaskBase;
      value: unknown;
    },
    replace: { key: keyof TaskInterface; value: unknown }
  ): Promise<TaskInterface> {
    const { key, value } = query;
    try {
      const task = (await TaskModel.findOne({ [key]: value })) as TaskInterface;
      if (!task) {
        throwError(
          `Insufficient query: ${query}`,
          Errors.insufficientQuery,
          __dirname,
          __filename
        );
      }
      task[replace.key] = replace.value; // This is where I get the error

      task.markModified(replace.key);
      task.save();
      return task;
    } catch (err) {
      console.log(err);
    }
  }
}

编辑:将替换参数更改为此

edit(query:{...}, replace: {key: keyof TaskBase, value: unknown}):
  Promise<TaskInterface> {
    // code here
    task[replace.key] = replace.value; // replaced replace.key for each key key manually
    // by doing `task["taskIdentifier"] = replace.value`, etc.
    // which DID NOT throw an error
}

现在它抛出以下错误: Type 'unknown' cannot be used as an index type.ts(2538)

【问题讨论】:

    标签: javascript typescript types


    【解决方案1】:

    unknown 与any 类似,但在类型检查时推断其类型。所以unknown不能被赋值为TaskInterface。然后,需要输入value,如下所示:

    async function edit<K extends keyof TaskInterface>(
        query: {
          key: keyof TaskBase;
          value: TaskBaseInterface[K];
        },
        replace: { key: keyof TaskBase; value: TaskBaseInterface[K] }
      ): Promise<TaskInterface | void> {
        const { key, value } = query;
       ...
    

    没有必要使用泛型,但我使用泛型是为了使代码易于阅读。

    【讨论】:

    • 太棒了!我不知道您可以使用密钥索引接口。既然您已经指出它确实看起来相当直观。帮了大忙,谢谢大佬!
    【解决方案2】:

    扩展 Akihito 的回答,这可能对你有用:

    async function edit<K extends keyof TaskInterface>(
      query: { key: keyof TaskBase; value: unknown; },
      replace: { key: K; value: TaskInterface[K]; }
    ): Promise<TaskInterface | void> {
      // ...
    }
    

    这样可以确保替换对象的key 和value 引用相同的属性,因此错误应该会消失。

    【讨论】:

    • 我确实按照这些思路实现了一些东西,谢谢!现在我尝试创建如下查询类型/接口:export type Query&lt;T&gt; = { key: keyof T; value: T[keyof T] }; 但显然这与您上面的不一样......
    • 你应该这样做 type Query&lt;T, K extends keyof T&gt; = { key: K; value: T[K] } 这样键和值都引用同一个属性。
    • 我也试过了,这就是我得到这个错误的地方:Type 'T[K]' cannot be used to index type 'TaskInterface'.ts(2536)
    • 这是一个最小的工作示例class Task implements TaskInterface {title: string;} interface TaskInterface {title: string;} type Query&lt;T, K extends keyof T&gt; = { key: K; value: T[K] } async function edit&lt;K extends keyof TaskInterface&gt;(replace: Query&lt;TaskInterface, K&gt;): Promise&lt;TaskInterface | void&gt; { const task = (new Task) as TaskInterface; task[replace.key] = replace.value; return task; }
    • 让我快速尝试一下 :p 编辑:是的,肯定有效 :D。这绝对应该作为修复我自己的参考。谢啦!非常感激。节日快乐!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2021-01-12
    • 2021-12-05
    • 2021-06-03
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多