我使用TypeScript输入以下内容:
const k = {
container: {
width: '100%',
},
}当我使用智能感知时,TypeScript发现我的对象k有一个名为container的属性似乎很酷。它工作得很好。现在,我想限制属性的值,所以我声明了一个接口:
interface StyleSet {
[key: string]: React.CSSProperties
}现在我将类型添加到前面的对象中,所以我们有:
const k: StyleSet = {
container: {
width: '100%',
},
}一切都很好。现在,智能感知可以识别,并且TypeScript强制对象k的属性值为React.CSSProperties类型。
然而,现在问题来了,现在智能感知(和TypeScript!?)不再识别我的k对象中的属性名称。也就是说,当我输入k.时,它不会提示(也似乎忽略)我之后输入的内容。所以我可以输入k.potatoe并使用这个值,没有任何问题(当然,这个值是undefined / null ),但是TypeScript不再提示任何错误。
问:我如何告诉TypeScript,属性的值都是React.CSSProperties类型的,但是当我使用对象时,仍然限制属性的名称?也就是说,我只能输入k.container。
我在网上搜索了大量的TypeScript文档和示例,但似乎这是不可能的。我尝试过接口、类型、记录、ReadOnly……
请注意,对象的键是未知的。例如,其中一个可能是:
const a: StyleSet = {
potato:{
width: '100%',
},
}而另一个对象可能是:
const b: StyleSet = {
ketchup: {
width: 'auto',
},
}另请注意,这里有一个部分解决方案,使用ReturnType TypeScript可以做我想做的事情,但我需要将每个对象包装在一个函数中。我也觉得这是无稽之谈。
欢迎任何想法:)
发布于 2020-09-17 14:51:28
这里有一种方法:
type PossibleKeys = 'container' | 'foo' | 'bar';
type StyleSet = {
// Question mark makes them optional properties.
// Otherwise TypeScript will require all keys in `PossibleKeys` to present.
[key in PossibleKeys]?: React.CSSProperties
}
const k: StyleSet = {
container: {
width: '100%',
},
}
// Now when you type `k.`, you will see three suggestions listed above.在此Playground Link中尝试。
更新
好的,你真正想要的是一组动态的键,基于给定的对象文字,并且你已经知道函数的解决方案,但是你不想使用它。然而,似乎在当前TypeScript的限制下,根本不可能存在更好的解决方案,原因如下。
首先,很明显,如果两个对象属于相同的(非泛型)类型,那么它们必须具有完全相同的成员(可能是可选的,但仍然是相同的键集)。因此,让不同的对象在以后有不同的键约束的唯一可能方式,就是让它们具有技术上不同的类型。显然,泛型类型将是您的最佳选择,其中泛型参数会导致不同的键约束。
因此,假设我们这样定义一个泛型类型:
type StyleSet<T extends string> = {
[k in T]: React.CSSProperties;
}但是,至少由于目前TypeScript的局限性,如果不使用函数,它就不能自动推断通用参数。例如,您不能这样写:
const a: StyleSet<> = ... // generic parameter must be explicitly given here因为目前还没有“部分类型推断”这样的东西;类型推断只有在我们完全省略了类型,并且可以从赋值的值中推断出来的时候才有效。如您所知,一种可能性是我们的函数解决方案:
function set<T extends string>(s: StyleSet<T>) { return s; }
const a = set({
container: {
width: "100%"
}
});然后,在本例中,我们的a被推断为StyleSet<"containter">。是的,您必须将每个对象文字包装在我们的函数set()中,但是正如我们刚才所分析的,您唯一的选择是显式地给出泛型参数:
const a: StyleSet<"container"> = {
container: {
width: "100%"
}
};这显然更糟糕,特别是当你在一个实例中有多个键的时候。有了函数解决方案,所有的键都会一次推断出来:
const b = set({
propA: { ... },
propB: { ... }
});
// b will become StyleSet<"propA" | "propB">发布于 2020-09-17 14:16:37
您正在创建StyleSet Index Type。如果仔细观察它,它不知道任何关于键的确切名称,它只知道,键可以是任何字符串。
Typescript也知道这么多信息。当您将StyleSet赋值给const k时,您丢失了密钥名称的信息。在代码的后面,typescript并不知道k包含container字段。
您可以做的是,如果您知道应该在StyleSet中提供的键的静态列表,那么您可以在类型本身中捕获它。使用索引类型,您将无法静态地访问它的字段。
https://stackoverflow.com/questions/63932202
复制相似问题