我想像这样定义一个递归的类型,基本上是:
interface CSSProperties {
marginLeft?: string | number
[key: string]?: CSSProperties
}
不幸的是,typescript docs说:
虽然字符串索引签名是描述“字典”模式的有效方式,但它们还强制所有属性都与其返回类型匹配。这是因为字符串索引声明obj.property也可用作obj [“property”]。在以下示例中,name的类型与字符串索引的类型不匹配,type-checker给出错误:
这似乎说这不可能用打字稿来表达,这似乎是一个严重的限制。 Flow做了我认为正确的事情,并假设marginLeft
不属于索引规范。
TypeScript中是否可以使用它?或者,有没有办法指定字符串是任何字符串但一组字符串?这样,我可以大致做一些事情:
interface NestedCSSProperties: CSSProperties {
[P not in keyof CSSProperties]?: CSSProperties
}
答案 0 :(得分:3)
这里的问题并不是真正的递归(允许),而是指出了你所指出的冲突签名。
我不确定当前行为的反面是否正确。对于我来说这似乎是一个主观决定,可以通过两种方式进行。按原样接受示例意味着您隐式合并定义;您可以查看其中一行并假设界面的效果,而另一行更改结果。写作确实感觉更自然,但是我不确定它是否安全,因为你通常不会对类型定义感到沮丧。
不管。 TypeScript确实允许与您期望的内容类似的行为,但您必须显式,因为字符串键也可以是string
或number
类型。这将有效:
interface CSSProperties {
marginLeft?: string | number,
[key: string]: CSSProperties|string|number,
}
例如,使用上面的界面,这是有效的:
let a: CSSProperties = {
marginLeft: 10,
name: {
marginLeft: 20,
}
};
这不是:
let a: CSSProperties = {
marginLeft: 10,
something: false, // Type 'boolean' is not assignable to type 'string | number | CSSProperties'.
something: new RegExp(/a/g), // Type 'RegExp' is not assignable to type 'CSSProperties'.
name: {
marginLeft: 20,
},
car: ["blue"], // Type 'string[]' is not assignable to type 'CSSProperties'.
};
它会正确地知道指定的成员:
let name1: string | number = a.marginLeft; // OK, return type is string | number
a.marginLeft = false; // Blocked, Type 'false' is not assignable to type 'string | number'.
a["whatever"] = false; // Blocked, Type 'false' is not assignable to type 'string | number | CSSProperties'.
a["marginLeft"] = false; // Blocked, Type 'false' is not assignable to type 'string | number'.
然而,问题在于,您需要在阅读时投射其他动态成员 - 它不会知道它是CSSProperties
。
这不会被阻止:
a["whatever"] = 100;
它会抱怨这个:
let name3: CSSProperties = a["name"]; // Type is CSSProperties | string | number
但如果明确地进行类型转换,这将有效:
let name3: CSSProperties = a["name"] as CSSProperties;
答案 1 :(得分:1)
在这种情况下,您必须包含字符串和数字。然后,您可以定义覆盖。使用这个例子,如果你试图将一个地图分配给'marginLeft',TS会抱怨,但会允许其他一切。
任何更多约束,您可能需要编写一个更深入的.d.ts文件,该文件可能使用映射类型。
您可以使用像Pick这样的预设映射类型来简化您的专属属性,但我承认,我有时很难将我的大脑包裹起来。
var picarioAPI = "where I pull the json file";
$.getJSON(picarioAPI, function (json) {
for (i in json)
if (json[i].CustId == {{ customer.id }}) {
答案 2 :(得分:1)
您是否尝试使用交叉点类型?
?- set_prolog_flag(answer_write_options,[max_depth(0)]).
true.
交叉点类型是界面继承的一种经常被忽略的,稍微强大的替代方法