typescript - 定义类型以使用类型选择的键创建对象似乎被破坏
问题描述
为什么这不起作用?
class Demo<T, ArrayOfKeysOfT extends (keyof T)[]> {
constructor(args: {[index in keyof ArrayOfKeysOfT]: T[ArrayOfKeysOfT[index]]}) {
args;
}
}
我得到的错误说
类型
ArrayOfKeysOfT[index]
不能用于索引类型T
。
但是,这段代码似乎应该没问题。我不确定这是设计使然还是 Typescript 中的错误。
更新
我意识到这里的问题是,类型结果ArrayOfKeysOfT[index]
在哪里不仅包含 的所有成员,而且通常包含数组的所有不同键(长度、推送、弹出等),这就是为什么它不能用于键入 T。index
keyof ArrayOfKeysOfT
ArrayOfKeysOfT
我想要完成的是以下内容。
说我定义了一些接口
interface Example {
one: string;
two: boolean;
}
那么这应该被允许
new Demo<Example, ['one', 'two']>({
one: "some string",
two: false
});
这应该会导致编译器错误,因为“两个”不在类型参数数组中
new Demo<Example, ['one']>({
one: "some string",
two: false
});
这应该会导致编译器错误,因为三不是第一个类型参数参数的键
new Demo<Example, ['one', 'two', 'three']>({
one: 'some string',
two: true,
three: 4
});
最后,这应该不起作用,因为分配给 args 对象中成员“two”的值类型错误
new Demo<Example, ['one', 'two']>({
one: "some string",
two: "another string"
});
解决方案
class Demo<T, ArrayOfKeysOfT extends (keyof T)[]> {
constructor(args: {[P in ArrayOfKeysOfT[number]]: T[P]}) {
console.log(args);
}
}
interface ABC {
a: number;
b: string;
c: boolean;
}
const demo1 = new Demo<ABC, ['a', 'b']>({ 'a': 0, 'b': 'hi' }); // works!
const demo2 = new Demo<ABC, ['a', 'd']>({ 'a': 0, 'd': null }); // ERROR - Type '["a", "d"]' does not satisfy the constraint '("a" | "b" | "c")[]'
const demo3 = new Demo<ABC, ['c']>({ 'c': 'not a boolean' }); // ERROR - Type 'string' is not assignable to type 'boolean'.
const demo4 = new Demo<ABC, ['b', 'c']>({ 'a': 0 }); // ERROR - argument of type '{ 'a': number; }' is not assignable to parameter of type '{ b: string; c: boolean; }'.
我很乐意提供帮助!
更新:
只是想提醒您(或让您知道)标准 TypeScript 库中存在内置Pick<T, K>
实用程序类型,这使得Demo
类型有点多余:
let a: Pick<ABC, 'a' | 'b'> = {'a': 2, 'b': 'hello'};
推荐阅读
- node.js - @import 'X' 媒体查询表达式必须以 '(' 开头,这对于带有 gatsby 的 sass 文件没有意义
- ios - 将 ipa 上传到应用程序加载器时出错
- javascript - 是否存在像 javascript es6 字符串模板文字这样的 Go 字符串模板?
- asp.net - 如何在 IIS 10 和 ASP Clasic 上添加 Etag 和 Last Modified Header?
- flutter - 当我使用扩展时隐藏类?
- c# - 如何从 EF Core 代码优先方法创建存储过程?
- javascript - 将库导入 laravel
- typescript - 环境上下文中的“const”初始值设定项必须是字符串或数字文字
- security - 禁用赛普拉斯测试的网络安全会保留状态 - 如何强制清理?
- php - 使用 AJAX 将与按钮无关的数据发送到模态