Coder Social home page Coder Social logo

Comments (8)

saltman424 avatar saltman424 commented on May 1, 2024 2

This auxilliary proposal allows instanceof to be placed prior to class or constructor variable, acting a qualifier.

(Note: I now think this proposal might be better than the main proposal in terms of user ease and simplicity - while solving the same problems).

Agreed. I don't think restricting instanceof to only be useable with interfaces would be desirable or necessary. However, there are some interesting cases, particularly when considering using extends:

For example, using this setup:

class A { ... }
class B extends A { ... }
class C { ... }

// Basic examples of `instanceof ...` being used where you would use other types
const a1: instanceof A = new A()
const a2: typeof a1 = a1
type InstanceOfA = instanceof A
interface AlsoInstanceOfA extends InstanceOfA {
}
const a3: AlsoInstanceOfA = new A()

These accurately represent the runtime, so they probably should be allowed:

const b1: instanceof A = new B()
const b2: (instanceof A) & B = new B()
const b3: (typeof a1) & B = new B()
const b4: (instanceof A) & (instanceof B) = new B()
type AB = (instanceof A) & (instanceof B) // could be simplified under-the-hood to `instanceof B` because B extends A

And these are not possible, so they should be never:

type BC = (instanceof B) & (instanceof C)
type IndirectAC = AlsoInstanceOfA & (instanceof C)

Also, presumably mapped types reduce an instanceof type to a plain structural type. E.g.

type MappedA = { [K in keyof InstanceOfA]: InstanceOfA[K] }
const a1: MappedA = new A()
const a2: InstanceOfA = a1 // Error: MappedA matches the structure of InstanceOfA but may not be an instance of A

Side Note: Boolean

@craigphicks I don't think your examples 1.2 and 2.3 do what you intend. My understanding is that would match filter(new Boolean()) (since new Boolean() instanceof Boolean === true) when I believe you are intending to match filter(Boolean) (but Boolean instanceof Boolean === false).

from typescript.

saltman424 avatar saltman424 commented on May 1, 2024 2

@craigphicks I think I understand your point: TypeScript currently only has structural types, so right now, typeof a can equally be interpreted as "the structural type of a" or "the entire type of a". So if this proposal is enacted, there has to be a decision on which of those two interpretations is correct. With that being said, my response is basically:

  1. I think it would break a lot of things if typeof only retrieved the structural type information (see another example below)
  2. I can't think of anything that wouldn't work as expected if typeof included all of the type information
  3. I don't think it would be confusing to developers if the official position was: typeof x is just the type of x, whatever that type may be (structural or non-structural)

Another edge case if typeof didn't support non-structural types:

function f<T>(foo: T): void {
  let temp: typeof foo = foo
  // Today this works. Would this stop working because `T` might be an `instanceof` type, like in the call below?
  foo = temp
}

f<instanceof A>(new A())

from typescript.

craigphicks avatar craigphicks commented on May 1, 2024 1

@saltman424 - Actually I was just about to remove those Boolean examples. That can be achieved by changing the type of the Boolean types converter (the expando function without new).

from typescript.

saltman424 avatar saltman424 commented on May 1, 2024 1

typeof instanceof A is not valid since instanceof A is a type, and typeof can only be used on a value. Assuming you meant something like:

const a: instanceof A
type X = typeof a

Then X would be instanceof A as a has a type of instanceof A

from typescript.

craigphicks avatar craigphicks commented on May 1, 2024

@saltman424 -

All good points. However about this one item - I'm not sure if you are saying this should or should not transfer the instanceof characterstic:

const a2: typeof a1 = a1

My gut feeling at this point is that typeof <instanceof> should maybe not be allowed because it is not clear if it should switch to structural, or keep instanceof. Carrying both could be a mistake because instanceof is generally sufficient and faster than a structural type check.

However, this is fine:

const b2: (instanceof A) & B = new B()

because it corresponds to a runtime use case where instanceof A and the structural members of B are required.

class A { ... }
class B extends A { x: number }
class C extends A { x: number, y: number }

declare function f(s:  (instanceof A) & B): void;
f(b2); // ok
f(new C()); // ok

This could also meaningfully occur:

const bc: instanceof B | instanceof C;

from typescript.

saltman424 avatar saltman424 commented on May 1, 2024

@craigphicks

I'm not sure if you are saying these should or should not transfer the instanceof:

I assumed it would transfer it. Basically, my interpretation is that const x: typeof y means x can be used anywhere that y can be used; or more simply, typeof y means exactly the type that y has, no alterations. Consider this example:

let a: instanceof A
a = ... as any as typeof a // this should always work, no matter the type of a

My gut feeling at this point is that typeof should maybe not be allowed because it is not clear if it should switch to structural, or keep instanceof. Carrying both could be a mistake because instanceof is generally sufficient and faster than a structural type check.

I think instanceof types will need to carry both the structural and instanceof information, as that is what would allow:

type AlwaysTrue<T extends object> = instanceof T extends T

We can't just use a nominal check in that case because consider this variation:

type AlwaysTrue<T extends object> = instanceof T extends Partial<T>

We need to be able to check instanceof T structurally against another type, so we need to carry the structural information as well. And with that being the case, I think it is reasonable for a developer to assume typeof will convey both the instanceof and structural type information about the variable being referenced

from typescript.

craigphicks avatar craigphicks commented on May 1, 2024

@saltman424 - Probably my terminology "carrying" is ambiguous and therefore bad. I won't use that anymore.

class A {}
const a: instanceof A = new A();

In logical terms a satisfies instanceof A implies a satisfies A, (but obviously not the opposite).

instanceof A & A simplifies to instanceof A.
instanceof A | A simplifies to A.

Does typeof instanceof A (*) mean instance A or A? Given the meaning of typeof to date, I would say A.

(*) typeof x, such that x satisfies instanceof A

from typescript.

craigphicks avatar craigphicks commented on May 1, 2024

@saltman424 - That could be a rule. But it isn't the only conceivable rule.

To date:

const a = new A();
type ALike = typeof a;

ALike is the category of all types that structurally extend A, including an infinite number of other types with extra properties, not limited to types with same constructor.

So that description would change. Again, it's not necessarily wrong that it would change. I'm just saying there is a qualitative fork in the road here that should be noted.

from typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.