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

Improve compatibility of hasProperty #80

Merged
merged 3 commits into from
Feb 14, 2023

Conversation

Gudahtt
Copy link
Member

@Gudahtt Gudahtt commented Feb 14, 2023

The hasProperty function is now compatible with a wider variety of objects. The Record<PropertyKey, unknown> constraint used previously was exluding Errors, and any object-like things expressed as a custom class or interface. Now all of those are accepted.

The `hasProperty` function is now compatible with a wider variety of
objects. The `Record<PropertyKey, unknown>` constraint used previously
was exluding `Error`s, and any object-like things expressed as a custom
class or interface. Now all of those are accepted.

// Using custom Error property is allowed after checking with `hasProperty`
if (hasProperty(exampleErrorWithCode, 'code')) {
expectType<unknown>(exampleErrorWithCode.code);
Copy link
Member Author

Choose a reason for hiding this comment

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

These tests were all failing prior to this change

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm... I'm wondering if a good change in the future would be to allow typing the property being checked. Something like:

if (hasProperty<number>(exampleErrorWithCode, 'code')) {
  expectType<number>(exampleErrorWithCode.code);
}

I guess we'll have to see how hasProperty ends up getting used.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm... I'm wondering if a good change in the future would be to allow typing the property being checked. Something like:

if (hasProperty<number>(exampleErrorWithCode, 'code')) {
  expectType<number>(exampleErrorWithCode.code);
}

I guess we'll have to see how hasProperty ends up getting used.

The problem with that is that we don't actually check the type, it's just being cast. It could be more useful if we combine it with a Superstruct struct.

import { number } from 'superstruct';

if (hasProperty(exampleErrorWithCode, 'code', number())) {
  expectType<number>(exampleErrorWithCode.code);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

@Mrtenz Ah — fair!

Copy link
Member Author

@Gudahtt Gudahtt Feb 14, 2023

Choose a reason for hiding this comment

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

We can combine hasProperty with a typeof check or another superstruct-based assertion easily enough.

I don't see us using this often in situations where we know something about the property already. If a property is known as optional, we could just use if (object.optionalProperty) to see if it exists. Establishing more information about the type of this unknown property would need some sort of runtime check as well.

@@ -101,14 +134,14 @@ expectNotAssignable<RuntimeObject>(Symbol('test'));
// The RuntimeObject type gets confused by interfaces. This interface is a valid object,
// but it's incompatible with the RuntimeObject type.
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface A {
interface RuntimeObjectInterfaceExample {
Copy link
Member Author

Choose a reason for hiding this comment

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

This was renamed to avoid a variable name conflict with the new test cases.

These names seem better anyway.

@Gudahtt Gudahtt marked this pull request as ready for review February 14, 2023 15:35
@Gudahtt Gudahtt requested a review from a team as a code owner February 14, 2023 15:35
These test modules are not meant to be compiled directly with
TypeScript. They sometimes include errors by-design that would blow up
if building with TypeScript.
tsconfig.json Outdated
@@ -12,5 +12,5 @@
"strict": true,
"target": "ES2017"
},
"exclude": ["./dist/**/*"]
"exclude": ["./dist/**/*", "./src/**/*.test-d.ts"]
Copy link
Member Author

Choose a reason for hiding this comment

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

Just added these two exclusions. These tsd modules are never intended to be compiled directly by TypeScript. That project uses a custom TypeScript fork instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

I had to undo this change because the linter relied on it. (Unsure why lint passed locally 🤔 I did run it. Maybe it was using cache data)

Instead I solved this by removing the expectError assertion, replacing it with expectNotAssignable. I guess we'll need to avoid expectError.

Mrtenz
Mrtenz previously approved these changes Feb 14, 2023
The type error assertion was replaced with an alternative that does not
introduce a compile-time error.
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Looks good!


// Using custom Error property is allowed after checking with `hasProperty`
if (hasProperty(exampleErrorWithCode, 'code')) {
expectType<unknown>(exampleErrorWithCode.code);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm... I'm wondering if a good change in the future would be to allow typing the property being checked. Something like:

if (hasProperty<number>(exampleErrorWithCode, 'code')) {
  expectType<number>(exampleErrorWithCode.code);
}

I guess we'll have to see how hasProperty ends up getting used.

@Gudahtt Gudahtt merged commit 5b6e31b into main Feb 14, 2023
@Gudahtt Gudahtt deleted the has-property-compatibile-with-errors branch February 14, 2023 18:02
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.

3 participants