[英]TypeScript: Typing Recursive Type
我有一个查询,我根据用户输入生成客户端,看起来像这样。
const query = {
"or": [
{
"field": "username",
"operator": "in",
"value": [
"jdoe",
"jsmith"
]
},
{
"and": [
{
"field": "email",
"operator": "matches",
"value": "/^gmail.com/"
},
{
"or": [
{
"field": "last_sign_in",
"operator": "lt",
"value": 1599619454323
},
{
"field": "last_sign_in",
"operator": "gt",
"value": 1489613454395
}
]
}
]
}
]
}
但是,为了将其迁移到简洁的 typescript 表示,我正在努力使其完全按照我想要的方式工作。
我有这些定义:
type Operator = 'eq' | 'in' | 'matches' | 'lt' | 'gt';
type Condition = 'and' | 'or' | 'not';
interface SimpleQuery {
field: string;
operator: Operator;
value: any;
}
interface Query {
condition: SimpleQuery[] // here I want `condition` to come from the type Condition
// I have tried these solutions involving [{ x of y }] https://github.com/microsoft/TypeScript/issues/24220
}
以下是我从 TS 编译器得到的错误:
A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
Cannot find name 'key'.
'Condition' only refers to a type, but is being used as a value here.
我试过这个
type Query = {
[key in Condition]: SimpleQuery[];
}
使用这种方法 typescript 也希望我也添加所有缺失的条件。
我认为这将是描述您描述的对象的最准确类型::
type Operator = 'eq' | 'in' | 'matches' | 'lt' | 'gt';
type UnionKeys<T> = T extends T ? keyof T : never;
type Condition = UnionKeys<OperatorExpression>;
interface FieldCondition {
field: string;
operator: Operator;
value: any;
}
type BinaryExpression<T extends PropertyKey> = {
[P in T] : [FieldCondition | OperatorExpression, FieldCondition | OperatorExpression]
}
type UnaryExpression<T extends PropertyKey> = {
[P in T] : [FieldCondition | OperatorExpression]
}
type OperatorExpression = BinaryExpression<"and"> | BinaryExpression<"or"> | UnaryExpression<"not">
const query: OperatorExpression = {
"or": [
{
"field": "username",
"operator": "in",
"value": [
"jdoe",
"jsmith"
]
},
{
"and": [
{
"field": "email",
"operator": "matches",
"value": "/^gmail.com/"
},
{
"or": [
{
"field": "last_sign_in",
"operator": "lt",
"value": 1599619454323
},
{
"field": "last_sign_in",
"operator": "gt",
"value": 1489613454395
}
]
}
]
}
]
}
此版本强制使用正确的逻辑运算符(使用元组类型)并基于运算符联合派生Condition
联合。
这就是你要的查询界面吗? 它适用于您的query
示例,但不确定它是否达到您想要的详细程度......
interface Query {
[key:string]: (SimpleQuery | Query)[];
}
我认为您需要在这里进行递归( 操场):
type Operator = 'eq' | 'in' | 'matches' | 'lt' | 'gt';
type Condition = 'and' | 'or' | 'not';
interface SimpleQuery {
field: string;
operator: Operator;
value: any;
}
type Query = {
[key in Condition]: Array<SimpleQuery | Query>;
}
const query: Query = {
"or": [
{
"field": "username",
"operator": "in",
"value": [
"jdoe",
"jsmith"
]
},
{
"and": [
{
"field": "email",
"operator": "matches",
"value": "/^gmail.com/"
},
{
"or": [
{
"field": "last_sign_in",
"operator": "lt",
"value": 1599619454323
},
{
"field": "last_sign_in",
"operator": "gt",
"value": 1489613454395
}
]
}
]
}
]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.