Comments (8)
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.
@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:
- I think it would break a lot of things if
typeof
only retrieved the structural type information (see another example below) - I can't think of anything that wouldn't work as expected if
typeof
included all of the type information - I don't think it would be confusing to developers if the official position was:
typeof x
is just the type ofx
, 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.
@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.
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.
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.
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.
@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.
@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)
- isolatedDeclarations should not have warning for functions that have no return statements HOT 4
- Trivia ownership documentation seems to be incorrect
- `--isolatedDeclarations` allows generator functions HOT 1
- Allow `--noCheck` on the CLI with top-level `--build`
- Union in template literal simplifying unexpectedly HOT 5
- Default import from an ESM package into a CommonJS project with esModuleInterop is faulty HOT 3
- Watch cannot handle large amount of file changes HOT 1
- generator next type should be inferred as union (instead of intersection) of yields' types OR just unknown
- Elementwise elaboration fails to be found for properties mixed with incompatible index signatures using intersections
- Error when accessing properties on `globalThis` with the same name of a global variable
- [NewErrors] 5.5.0-dev.20240428 vs 5.4.5 HOT 49
- Private class properties prevent `Readonly` type inference HOT 2
- [ServerErrors][TypeScript] 5.5.0-dev.20240428 HOT 12
- [ServerErrors][JavaScript] 5.5.0-dev.20240428 HOT 9
- Strange runtime caching bug involving `as const` and `const T` generic HOT 1
- When relatively importing a `.d.ts` file in a declaration file, TypeScript loads a `.ts` file instead HOT 7
- Calling decorators with @ loses type safety with function as argument HOT 2
- Include error maps in the typescript libraries for web apis to give developers easy access to potential thrown exceptions HOT 5
- jsdoc @type does not resolve a type
- Removing `node_modules`, running `npm ci` leaves diagnostics behind in ts and tsconfig files
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typescript.