TypeScript:从 Record<> 接口继承值的类型,而不是所有的键
TypeScript: Inherit the type of values, not all the keys, from a Record<> interface
我的项目中有一个主界面,它规定了扩展对象属性的 value
类型。
为了简单起见,我们假设是这样的:
interface Printable extends Record<PropertyKey, string> {
}
它只是说所有 value
应该是 string
。并且它正确地禁止其扩展接口具有 number
键,如下所示。
interface Receipt extends Printable {
customerName: string;
// customerId: number; // EXPECTED: This line errors if uncommented (Property 'customerId' of type 'number' is not assignable to string index type 'string'. (2411))
}
然而,不需要的副作用是它将“键”范围扩大为“任何 string
”,因此它不会捕获以下错误:
const r: Receipt = { customerName: "Jack" };
console.log(r.address); // UNEXPECTED: This line DOESN'T error "for Property 'address' does not exist on type 'Receipt'.(2339)"
问题
如何从超级接口中获得“强制值类型”的好处,而不需要不需要的“加宽键范围” ?
PS。它与 TypeScript: Create typed Record without explicitly defining the keys 的不同之处在于,在这里我想要一个 接口 并且没有对象或其实例化的开销。请停止将其报告为重复项。 :)
我认为至少现在不可能,因为你必须这样做:
interface Printable extends Record<keyof Printable, string> {
}
这给出了关于递归使用 Printable interface
的错误并且没有多大意义 tbh。我想到的唯一解决方案如下所示。
type StringOnly<T extends string> = Record<T, string>
type Printable = StringOnly<"key1" | "key2" | "key3">
interface Receipt extends Printable {
customerName: string;
}
const r: Receipt = { customerName: "Jack"};
console.log(r.address); // Property 'address' does not exist on type 'Receipt'.(2339)
您可以根据 generic type constraint 创建实用程序类型以验证输入类型值:
type Printable<T extends Record<PropertyKey, string>> = T;
type Receipt = Printable<{
customerName: string;
// customerId: number; // Expect error
}>
const r: Receipt = { customerName: "Jack" };
console.log(r.address); // Property 'address' does not exist on type '{ customerName: string; }'.
我的项目中有一个主界面,它规定了扩展对象属性的 value
类型。
为了简单起见,我们假设是这样的:
interface Printable extends Record<PropertyKey, string> {
}
它只是说所有 value
应该是 string
。并且它正确地禁止其扩展接口具有 number
键,如下所示。
interface Receipt extends Printable {
customerName: string;
// customerId: number; // EXPECTED: This line errors if uncommented (Property 'customerId' of type 'number' is not assignable to string index type 'string'. (2411))
}
然而,不需要的副作用是它将“键”范围扩大为“任何 string
”,因此它不会捕获以下错误:
const r: Receipt = { customerName: "Jack" };
console.log(r.address); // UNEXPECTED: This line DOESN'T error "for Property 'address' does not exist on type 'Receipt'.(2339)"
问题
如何从超级接口中获得“强制值类型”的好处,而不需要不需要的“加宽键范围” ?
PS。它与 TypeScript: Create typed Record without explicitly defining the keys 的不同之处在于,在这里我想要一个 接口 并且没有对象或其实例化的开销。请停止将其报告为重复项。 :)
我认为至少现在不可能,因为你必须这样做:
interface Printable extends Record<keyof Printable, string> {
}
这给出了关于递归使用 Printable interface
的错误并且没有多大意义 tbh。我想到的唯一解决方案如下所示。
type StringOnly<T extends string> = Record<T, string>
type Printable = StringOnly<"key1" | "key2" | "key3">
interface Receipt extends Printable {
customerName: string;
}
const r: Receipt = { customerName: "Jack"};
console.log(r.address); // Property 'address' does not exist on type 'Receipt'.(2339)
您可以根据 generic type constraint 创建实用程序类型以验证输入类型值:
type Printable<T extends Record<PropertyKey, string>> = T;
type Receipt = Printable<{
customerName: string;
// customerId: number; // Expect error
}>
const r: Receipt = { customerName: "Jack" };
console.log(r.address); // Property 'address' does not exist on type '{ customerName: string; }'.