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

Assigning excess properties can break type system #177

Open
kaleidawave opened this issue Jul 21, 2024 · 3 comments
Open

Assigning excess properties can break type system #177

kaleidawave opened this issue Jul 21, 2024 · 3 comments
Assignees
Labels
bug Something isn't working checking Issues around checking

Comments

@kaleidawave
Copy link
Owner

The following with ?: passes through the type system (at least will after #122) but throws at runtime

function func(param: { prop: string }) {
	const v1: { excess?: number } = param;
	const v2: number = v1.excess ?? 0;
	return Math.sin(v2)
}

func({ prop: "", excess: console })

This is also true for union types

function func(param: { prop: string }) {
	const v1: {} | { excess: number } = param;
	const v2: number = v1.excess ?? 0;
	return Math.sin(v2)
}

func({ prop: "", excess: console })

The problem is sort of related to narrowing because the v1.excess ?? performs narrowing (number | undefined -> number). Maybe narrowing checks could be added during event application but would like to avoid that. (I should raise a related issue around getter property narrowing)


The Exclusive<...> helper type (to be added in #157) can help here (although that is opt in and not in TSC). Maybe a mode could enforce this for assigning to unions and conditional properties. Want to not ignore this issue while also not creating something that is too strict (and creates a lot of breaking changes).

@kaleidawave kaleidawave added bug Something isn't working checking Issues around checking labels Jul 21, 2024
@kaleidawave kaleidawave self-assigned this Jul 21, 2024
@kaleidawave
Copy link
Owner Author

Note this is also an issue in TSC (microsoft/TypeScript#12936).

Some cases are currently caught by ezno-checker because objects are treated dependently (for variables: it separates assignment restrictions from current values)

const x: {} = { b: "hi" }
const y: { b?: number } = x;
y.b satisfies boolean; // fails with = "hi"

(+ because of assignment tracking via events)

const x: { b: string } = { b: "hi" };
const y: {} = x;
const z: { b?: number } = y;
(function () { z.b = 5; })();
x.b satisfies string; // fails with = number

The issue is around what happens when we don't have the dependent types.

@RobertSandiford
Copy link

RobertSandiford commented Jul 31, 2024

See my comment on TS Exact types here: microsoft/TypeScript#12936 (comment)

A value that is structurally typed (may have excess properties) cannot be safely assigned to a type that includes an optional property that is not present on the type of the value. Only an exact typed object or a fresh object (that we have full information on) can be assigned to a type with an additional optional property. I talked about a type that would work this was called a noextend type.

Spoken from a TS perspective - I'm not familiar with the workings of ezno. If I was making a rational type system I would make basic types work the noextend way instead of implementing them the TS way.

@kaleidawave
Copy link
Owner Author

See my comment on TS Exact types here: microsoft/TypeScript#12936 (comment)

The link shoes a good example for a fail that can occur.

With any solution to this I would like to make it somewhat TSC compatible. Technically from subtyping rules excess properties are fine, the problem is that TSC removes information (etc the extra properties) for variable type annotations.

With the more dependent type system that is aware of mutations through side effects, your example should raise an issue already (or very soon from #157) from ezno check.

Maybe there could be a flag so that all user code is subjected to all type object type annotations being treated as the upcoming Exclusive helper will work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working checking Issues around checking
Projects
None yet
Development

No branches or pull requests

2 participants