最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Superstruct validation for object with dynamic fields - Stack Overflow

programmeradmin6浏览0评论

I am currently using superstruct to type and validate an object. This object is returned via an API and then validated and type cast using the superstruct struct.

The structure of the object depends on a list of strings I only have at runtime, an example is below. There can be an arbitrary number of these arbitrary fields but they always have the same structure.

{
  parent: 
  {
    thisFieldIsAlwaysHere: number;
    arbitraryObject1: { body: number; };
    arbitraryObject2: { body: number; };
    arbitraryObject3: { body: number; };
  }
}

For this I use a struct with a record with a string for the name and the object for the body of each of these which are the same like so

const Struct = type({
  parent: record(string(), type({ body: number() }))
})

This is fine with typescripts types when using infer to cast. But my object fails to validate due to thisFieldIsAlwaysHere being a number not an object. Including thisFieldIsAlwaysHere using an intersection does not help. It appears the record is applied to every field.

const Struct = type({
  parent: intersection([
    type({ thisFieldIsAlwaysHere: number()),
    record(string(), type({ body: number() }))
  ])
})

Is there a way to get this to work elegantly? I have tried using dynamic. I was wondering if there is a way to exclude certain field names from the record? Or potentially exlclude other fields in the type

I am currently using superstruct to type and validate an object. This object is returned via an API and then validated and type cast using the superstruct struct.

The structure of the object depends on a list of strings I only have at runtime, an example is below. There can be an arbitrary number of these arbitrary fields but they always have the same structure.

{
  parent: 
  {
    thisFieldIsAlwaysHere: number;
    arbitraryObject1: { body: number; };
    arbitraryObject2: { body: number; };
    arbitraryObject3: { body: number; };
  }
}

For this I use a struct with a record with a string for the name and the object for the body of each of these which are the same like so

const Struct = type({
  parent: record(string(), type({ body: number() }))
})

This is fine with typescripts types when using infer to cast. But my object fails to validate due to thisFieldIsAlwaysHere being a number not an object. Including thisFieldIsAlwaysHere using an intersection does not help. It appears the record is applied to every field.

const Struct = type({
  parent: intersection([
    type({ thisFieldIsAlwaysHere: number()),
    record(string(), type({ body: number() }))
  ])
})

Is there a way to get this to work elegantly? I have tried using dynamic. I was wondering if there is a way to exclude certain field names from the record? Or potentially exlclude other fields in the type

Share Improve this question asked 6 hours ago user16717440user16717440 335 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The current way I have gotten around this is by using coerce. This allows for transformation pre validation. Then when the invalid content is encountered it can be transformed into the correct one. You need to use create instead of assert though. The example is

const Struct = type({
  parent: record(
            string(),
            coerce(type({ body: number() }), number(), (value) => ({ body: value })))
})

Unfortunately this still does not answer how to validate a partially dynamic type like this but still provides a work around at least

发布评论

评论列表(0)

  1. 暂无评论