首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将固定类型值赋给泛型约束类型的partial?

如何将固定类型值赋给泛型约束类型的partial?
EN

Stack Overflow用户
提问于 2021-04-09 04:13:11
回答 1查看 40关注 0票数 1

对于可能有Ids的事物,我有一个基本的接口:

代码语言:javascript
复制
interface Identifiable {
    id?: number;
}

我有一个泛型函数,可以将一个记录对象转换为一个id为的东西:

代码语言:javascript
复制
function fromRowToObj1<T extends Identifiable>(row: { id: number; }): Partial<T> {
    return { id: row.id };
    // Type '{ id: number; }' is not assignable to type 'Partial<T>'.
}

我知道发生这种情况是因为有一些扩展IdentifiableT会使该返回语句非法。例如,类型{ id: undefined }{ id: 1 }。因此我决定对返回类型进行一些调整,以强制使用数字id:

代码语言:javascript
复制
type Identified<T extends Identifiable> = {
    [K in keyof T]?: K extends "id" ? number : T[K];
}
// Should give something like type C = { id?: number | undefined; ... }

function fromRowToObj2<T extends Identifiable>(row: { id: number; }): Identified<T> {
    return { id: row.id };
    // Type '{ id: number; }' is not assignable to type 'Identified<T>'.
}

但是为什么呢?哪种可能的T (例如T extends Identifiable)使它不能将{ id: number }赋值给Identified<T>

如果无法调整Identified类型以使其正常工作,是否有其他方法可以键入转换函数以使用Identifiable的泛型子类型

Link to playground

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-09 06:03:40

您所面临的问题已在here中得到了全面的描述。正如您所注意到的,T extends Identifiable的一些子类型使得返回值{ id: row.id }无效。例如,Identified<{id?: never}>永远不会对{ id: row.id }有效。Never仍然是id的有效类型,因为您已将Identified的所有键声明为可选。如果为T extends Identifiable,则Identified<T>实际上等于Partial<T>。Typescript正确地在这里抛出一个错误。但是,如果您设置了有效的默认值(playground),您仍然可以解决这个问题:

代码语言:javascript
复制
interface Identifiable {
    id?: number;
}

// results in optional id
function fromRowToObj1<T extends Identifiable>(row: { id: number; }) {
    const result: Partial<T> = {} // valid for all subtypes of Partial<T>
    result.id = row.id
    return result;
}

// results in non optional id
function fromRowToObj2<T extends Identifiable>(row: { id: number; } ) {
    const partial: Partial<T> = {}; // valid for all subtypes of Partial<T>
    const result = {
        ...partial,
        id: row.id
    };
    return result;
}

interface TestObject {
    id: number,
    arg1: string;
    arg2: boolean;
}

const result1 = fromRowToObj1<TestObject>({id: 5});
result1.id // optional
result1.arg1 = "test" // intellisense works
result1.arg2 = true; // intellisense works

const result2 = fromRowToObj2<TestObject>({id: 5});
result2.id // not optional
result2.arg1 = "test" // intellisense works
result2.arg2 = true; // intellisense works
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67011244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档