ts-reset icon indicating copy to clipboard operation
ts-reset copied to clipboard

Make WeakSet.has() and WeakMap.has() accept `unknown` and assert type.

Open DeepDoge opened this issue 2 years ago • 1 comments

It's annoying when you have a value with unknown type and can't use it inside .has() or .delete() function. Which doesn't make sense at all. unknown should be allowed and also .has() should assert type.

Solution:

interface WeakSet<T extends WeakKey> {
    delete<V>(value: V & (unknown extends V ? unknown : T)): value is T
    has<V>(value: V & (unknown extends V ? unknown : T)): value is T
}

Result:

interface Foo {
    foo: string
}

interface Bar {
    bar: string
}

const foo: Foo = { foo: "foo" }
const bar: Bar = { bar: "bar" }

const unknownFoo: unknown = foo satisfies Foo

const fooSet = new WeakSet<Foo>()

if (fooSet.has(unknownFoo)) {
    unknownFoo.foo // Foo
}

if (fooSet.has(foo)) {
    foo.foo // Foo
}

if (fooSet.has(bar)) { // Error: No overload matches this call.
    bar.foo // Foo
}

Same thing can be done for the WeakMap

DeepDoge avatar Jan 01 '24 13:01 DeepDoge

The type predicates in these definitions are unsafe, see https://github.com/total-typescript/ts-reset/pull/125#issuecomment-1926133512

russelldavis avatar Feb 05 '24 02:02 russelldavis