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

Exact not function correctly with Dates since last commit #909

Closed
nlynzaad opened this issue Jul 8, 2024 · 8 comments
Closed

Exact not function correctly with Dates since last commit #909

nlynzaad opened this issue Jul 8, 2024 · 8 comments

Comments

@nlynzaad
Copy link

nlynzaad commented Jul 8, 2024

Hi,

First off, I'm a new user of the project and just want to say thanks for your efforts in maintaining this exceptionally handy project.

Was struggling to get the Exact type to work and it seems to be related to a change that was made in commit #902, specifically the change from object to JsonObject. When having a date field, the validation does not throw an error as expected. The error however does appear in the version prior to the commit and in the new version if the Date field is removed.

import type {Exact, IsEqual, JsonObject} from "type-fest";
import type {ArrayElement} from "type-fest/source/internal";
import type {TagContainer} from "type-fest/source/opaque";
import {ExactObject} from "type-fest/source/exact";

type UserType = {
	id: string,
	name: string,
	createdAt: Date,
	email?: string,
};

type UserTypeWithoutDate = {
	id: string,
	name: string,
	email?: string | undefined,
};

const testValues = {
	id: 'asd',
	name: 'John',
	createdAt: new Date(),
	email: undefined,
	surname: 'Doe',
};

const testValuesWithoutDate = {
	id: 'asd',
	name: 'John',
	email: undefined,
	surname: 'Doe',
};

export type Exact_OLD<ParameterType, InputType> =
	IsEqual<ParameterType, InputType> extends true ? ParameterType
		// Convert union of array to array of union: A[] & B[] => (A & B)[]
		: ParameterType extends unknown[] ? Array<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
			// In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray.
			: ParameterType extends readonly unknown[] ? ReadonlyArray<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
				// Leave tagged types as-is. We could try to make the untagged part Exact, and just leave the tag as-is, but that seems to create instanitation excessively deep errors.
				: ParameterType extends TagContainer<unknown> ? ParameterType
					: ParameterType extends object ? ExactObject<ParameterType, InputType>
						: ParameterType;

export type Exact_NEW<ParameterType, InputType> =
	IsEqual<ParameterType, InputType> extends true ? ParameterType
		// Convert union of array to array of union: A[] & B[] => (A & B)[]
		: ParameterType extends unknown[] ? Array<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
			// In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray.
			: ParameterType extends readonly unknown[] ? ReadonlyArray<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
				// Only apply Exact for pure object types. For types from a class, leave it unchanged to TypeScript to handle.
				: ParameterType extends JsonObject ? ExactObject<ParameterType, InputType>
					: ParameterType;

function oldExactFunc <T extends Exact_OLD<UserType, T>>(user: T) {
	return user
}

function newExactFunc <T extends Exact_NEW<UserType, T>>(user: T) {
	return user
}

function newExactFuncWithoutDate <T extends Exact_NEW<UserTypeWithoutDate, T>>(user: T) {
	return user
}
const oldExactResult = oldExactFunc(testValues) //this errors correctly
const newExactResult = newExactFunc(testValues) //this does not error.
const newExactResultWithoutDate = newExactFuncWithoutDate(testValuesWithoutDate) //this errors correctly.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@nlynzaad nlynzaad changed the title Exact not function correctly with optionals since last commit Exact not function correctly with Dates since last commit Jul 8, 2024
@sindresorhus
Copy link
Owner

// @zorji

@zorji
Copy link
Contributor

zorji commented Jul 9, 2024

Hi @nlynzaad

I am trying to reproduce the issue but I can't in my IDE. Just want to clarify this with you, are you expecting the Exact type to throw error because surname is the excess field? I also noticed that email should be reported as well as the type does not allow undefined but the field can be optional.

image

@nlynzaad
Copy link
Author

nlynzaad commented Jul 9, 2024

Hi @zorji ,

Thanks for looking into this.

Yes I'm expecting it to fail due to the additional "surname" property. I usually work in webstorm where I picked this issue up, confirmed now with vscode the editor show it as well and tsc also only fails using EXACT_OLD or with no date field

image

@nlynzaad
Copy link
Author

nlynzaad commented Jul 9, 2024

for testing I got EXACT_OLD from the pre-commit diff and EXACT_NEW from current master.

@nlynzaad
Copy link
Author

nlynzaad commented Jul 9, 2024

I created a stackblitz with the issue: Exact Issue

@zorji
Copy link
Contributor

zorji commented Jul 9, 2024

@nlynzaad Thanks I can reproduce it when using a variable. Let me see if I can provide a fix.

@zorji
Copy link
Contributor

zorji commented Jul 9, 2024

I drafted this fix #911

Do you mind help test if that fixes the issue for you?

@nlynzaad
Copy link
Author

nlynzaad commented Jul 9, 2024

@zorji Thanks a lot.

I copied the draft into the larger project and worked as intended

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

No branches or pull requests

3 participants