Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for additionalProperties #30

Merged
merged 1 commit into from
Feb 15, 2020
Merged

Add tests for additionalProperties #30

merged 1 commit into from
Feb 15, 2020

Conversation

bigpopakap
Copy link
Contributor

I like to be able to set additionalProperties: false in schemas so that Ajv's removeAdditional: true option (enabled in #29) can strip out extra properties when a schema says so. (Here are the docs about the removeAdditional option)

@bigpopakap
Copy link
Contributor Author

bigpopakap commented Feb 10, 2020

I broke this out from #29 as requested here. Unfortunately, it's a little confusing right now because this PR includes the commits from #29 since the test I need to be able to pass options to ajv

UPDATE: rebased/synced this PR so now it just includes the single relevant commit

@@ -108,7 +108,7 @@ type PropertiesConstraint<
: unknown;

type AdditionalPropertiesConstraint<
AdditionalProperties extends SchemaLike | undefined
AdditionalProperties extends SchemaLike | (false | undefined)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recreating my original comment from the other PR here:

I didn't want to allow additionalProperties: true, so I'm specifically doing (false | undefined) instead of (boolean | undefined)

@@ -306,6 +306,30 @@ describe("More involved tests with objects", () => {
const toFail = {};
expect(() => parser.parse(JSON.stringify(toFail))).toThrow();
});

test("Object disallowing additionalProperties", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recreating my original comment from the other PR here:

Let me know if you want me to add another test where the schema defined additionalProperties: false, but the removeAdditional option is omitted. I thought that might be overkill since that's more towards testing ajv's internals, which we may not need to worry about here.

@ostrowr
Copy link
Owner

ostrowr commented Feb 10, 2020

I haven't checked this out and tried it yet, so I might be misunderstanding the intended use case here – but boolean should be assignable to SchemaLike. I think just writing S(false) rather than false will accomplish what you're looking to do here without having to widen the type of additionalProperties.

@bigpopakap
Copy link
Contributor Author

Oh wow, yes, I also just noticed #26! I must have tried this before that change landed, and hadn't tested it again since then. That looks like it'll work. I'll give it a shot sometime today, and close this PR if it's been solved.

@@ -308,6 +308,175 @@ describe("More involved tests with objects", () => {
});
});

describe("additionalProperties", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ostrowr these tests are better at highlighting what I'm trying to fix. The type checking is a little off when mixing properties with additionalProperties. These tests that I have added fail both with and without my changes to json-schema.ts. I.e. the issue exists in the current master branch, and my changes to json-schema.ts do not fix them.

It seems very difficult to get better type checking for this scenario, so I'd appreciate any pointers or suggestions you may have and I'll be happy to continue working on this.

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, but I wanted to say anyway: I found the expectType() function quite clever! That was a nifty way to quickly and easily do typing tests

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

I'm going to take a closer look at this PR tonight/tomorrow – appreciate the new tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You know this code way better than I do, but my guess is that the fix will require combining PropertiesConstraint and AdditionalPropertiesConstraint the same was that AdditionalItems is included in ItemsConstraint

Ex.

PropertiesConstraint<
  Properties extends { [k: string]: SchemaLike } | undefined,
  Required extends readonly (keyof Properties)[] | undefined,
  AdditionalProperties extends SchemaLike | undefined // add this, and remove AdditionalPropertiesConstraint
> = // stuff

I don't know if it's possible in Typescript to define an `object like this:

type PropertiesConstraint  = {
    [P in keyof Properties]: Properties[P][typeof InternalTypeSymbol],
    [k: /* all other properties */]: unknown
}

so for additionalProperties: S(true) the best might be that it gives you { [k: string]: unknown } and loses all type information for properties. But for additionalProperties: S(false), it's probably possible to have it revert back to the properties schemas.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems like a perfect typing is blocked by microsoft/TypeScript#17867

Individual property access seems to be correctly typed, it's just the expectType<Validated<typeof schema>>(...) checks that fail.

This may just be impossible at this point, unfortunately.

@bigpopakap
Copy link
Contributor Author

I just push some updates. It still isn't completely done (sorry for the noise), but I think this PR gets a little closer to a solution now. I'll clean up the tests sometime soon, and will push another version that actually proposes a full solution.

@bigpopakap
Copy link
Contributor Author

Ok, I think this PR is in its final state. I don't think it's possible to do any better than is already there. I added some tests for some expected behavior. Some assertions are commented out and reference a Typescript issue that's blocking them, mostly for documentation. If you find these tests useful, we can merge this PR. Otherwise, I don't think there is any feature improvement I can make here.

Thank you for all your time and attention!

@bigpopakap bigpopakap changed the title Allow setting additionalProperties to false Add tests for additionalProperties Feb 14, 2020
@ostrowr
Copy link
Owner

ostrowr commented Feb 15, 2020

OK, this all makes sense! This type system isn't quite sound but is hopefully still useful for your use-case.

I'll go ahead and merge these new tests!

one thing to note is that the expectType function isn't actually that useful – if the thing you're testing is assignable to the thing you're expecting, then it will return true even if they're not exactly equal. I have an idea about how to improve this and will push that up shortly, then cut a release so everyone can use the ajv properties.

@ostrowr ostrowr merged commit 19cf111 into ostrowr:master Feb 15, 2020
@bigpopakap
Copy link
Contributor Author

Thank you @ostrowr!

Yeah, it'll be great to get a new version so I can start using the ajv properties. And I'm glad you found these tests useful.

The type system is actually quite great! I think this whole project is super useful and well done. Having this simple Typescript wrapper around JSON schemas is more than enough for my use cases. I understand that not all JSON schema features will be replicable in Typescript, but you've documented all of them really well in the README. And in this particular case, it seems like we're limited by Typescript itself.

I look forward to seeing what you do about the expectType function! As I was writing these tests, it did occur to me that, like you say, something like expectType<unknown> is not very useful :P Would you mind tagging me in a PR or commit so I can see what you do (just for my own learning)?

@ostrowr
Copy link
Owner

ostrowr commented Feb 17, 2020

I look forward to seeing what you do about the expectType function! As I was writing these tests, it did occur to me that, like you say, something like expectType is not very useful :P Would you mind tagging me in a PR or commit so I can see what you do (just for my own learning)?

@bigpopakap I'm not sure if I'm going to merge this, because working on the branch it's pretty clear that I'm going to have to write some crazy types to get tests to pass typechecking, but https://github.com/ostrowr/ts-json-validator/compare/expect-true is the basic idea. Same equality relation I use in https://ostro.ws/2019/12/09/taking-types-too-far/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants