Typescript泛型类型检查失败 //RepositoryBase.ts 导出类型FieldsMapping={readonly[k in keyof Required]:string}; 导出抽象类RepositoryBase{ 受保护的摘要只读列:字段映射; } //UsersRepository.ts 从“/RepositoryBase”导入{FieldsMapping,RepositoryBase}; 界面用户{ 名字:字符串; lastName:string; 电子邮件?:字符串; } 导出类UsersRepository扩展了RepositoryBase{ 受保护的只读列={ 名字:“名字”, 姓氏:“姓氏”, 电子邮件:“电子邮件”, 额外:“非现有列”, }; }

Typescript泛型类型检查失败 //RepositoryBase.ts 导出类型FieldsMapping={readonly[k in keyof Required]:string}; 导出抽象类RepositoryBase{ 受保护的摘要只读列:字段映射; } //UsersRepository.ts 从“/RepositoryBase”导入{FieldsMapping,RepositoryBase}; 界面用户{ 名字:字符串; lastName:string; 电子邮件?:字符串; } 导出类UsersRepository扩展了RepositoryBase{ 受保护的只读列={ 名字:“名字”, 姓氏:“姓氏”, 电子邮件:“电子邮件”, 额外:“非现有列”, }; },typescript,generics,Typescript,Generics,UsersRepository中列的声明不会给出任何编译错误,即使User界面上不存在extra键 如果我将类型添加到UserRepository中的列中,例如:COLUMNS:FieldsMapping,则会引发错误 我不想在继承RepositoryBase的每个类上重新声明类型。你知道为什么会这样吗?可能是由于摘要?或者可能是由于tsconfig.json中的某些配置造成的?知道怎么解决吗?const userLike={ 名字:'', 姓氏:“”, 电子邮件:“”, az:' }; con

UsersRepository
列的声明不会给出任何编译错误,即使
User
界面上不存在
extra

如果我将类型添加到
UserRepository
中的
列中,例如:
COLUMNS:FieldsMapping
,则会引发错误

我不想在继承
RepositoryBase
的每个类上重新声明类型。你知道为什么会这样吗?可能是由于
摘要
?或者可能是由于
tsconfig.json
中的某些配置造成的?知道怎么解决吗?

const userLike={
名字:'',
姓氏:“”,
电子邮件:“”,
az:'
};
const user:user=userLike;
Typescript允许这种“灵活”的分配。他对申报更严格


关于这个问题有一个有趣的建议:

当您使用
扩展接口或类时,您可以通过添加新属性或缩小现有属性来缩小子接口/子类。因此,在TypeScript中,
UserRepository
COLUMNS
属性比
RepositoryBase
COLUMNS
属性更具体是完全可以接受的。这就是
扩展
的明确目的

如果您选择将
属性
用户存储库
的类型注释为
记录
(相当于您的
字段映射
),并在分配中使用新的对象文字,您将获得并标记额外的属性

如果这对你有用的话,你应该去做。。。它有点多余(您必须在
RepositoryBase
的泛型参数和
属性的注释中写入
User
),但相当干净

否则,我没有任何很好的修复方法,主要是因为
protected
属性很难通过编程进行操作。(例如,
UserRepository的键
不包括
,因此
UserRepository[“列”]
无效)

我想我能得到的最接近的方法是一个名为
strictColumns()
的通用方法,它只接受没有已知额外属性的字段映射。。。该方法将只返回其输入,因此您可以使用它初始化
属性:

// RepositoryBase.ts
export type FieldsMapping<T> = { readonly [k in keyof Required<T>]: string };

export abstract class RepositoryBase<T> {
    protected abstract readonly COLUMNS: FieldsMapping<T>;
}

// UsersRepository.ts
import { FieldsMapping, RepositoryBase } from './RepositoryBase';

interface User {
    firstName: string;
    lastName: string;
    email?: string;
}

export class UsersRepository extends RepositoryBase<User> {
    protected readonly COLUMNS = {
        firstName: 'first_name',
        lastName: 'last_name',
        email: 'email',
        extra: 'non_existing_column',
    };
}
抽象类RepositoryBase{
受保护的摘要只读列:记录;
狭窄柱<
U扩展{[K in keyof T | keyof U]:K扩展keyof T?string:never}
>(u:u){
返回u;
}
}
像这样:

abstract class RepositoryBase<T> {
  protected abstract readonly COLUMNS: Record<keyof T, string>;
  strictColumns<
    U extends { [K in keyof T | keyof U]: K extends keyof T ? string : never }
  >(u: U) {
    return u;
  }
}
class UsersRepository扩展了RepositoryBase{
受保护的只读列=this.strictColumns({
名字:“名字”,
姓氏:“姓氏”,
电子邮件:“电子邮件”
});
}//好的
类BadUsersRepository扩展了RepositoryBase{
受保护的只读列=this.strictColumns({
名字:“名字”,
姓氏:“姓氏”,
电子邮件:“电子邮件”,
额外:“额外”//error!字符串不可分配给never
});
}
这是可行的,但增加的复杂性可能不值得稍微减少冗余。哦,好吧

希望有帮助。祝你好运

class UsersRepository extends RepositoryBase<User> {
  protected readonly COLUMNS = this.strictColumns({
    firstName: "first_name",
    lastName: "last_name",
    email: "email"
  });
} // okay

class BadUsersRepository extends RepositoryBase<User> {
  protected readonly COLUMNS = this.strictColumns({
    firstName: "first_name",
    lastName: "last_name",
    email: "email",
    extra: "extra" // error! string is not assignable to never
  });
}