text:
Constraint Types Proposal

Edit: Now a gist, with all the previous edits erased.
See this gist for the current proposal. Better there than a wall of text here.

Why not use a ternary operator?
Instead of:
let other: (value is number: string | value is string: boolean)

This:
let other: (value is number ? string : value is string ? boolean)

Looks less confusing for me.

this is what they call dependent types, isnt it?

if so, is predicate alone looks too constraining (pun intended) it should be any predicate:
type T where T is string when A is number && A > 123;

@aleksey-bykov It's not quite dependent types, because values cannot be lifted to types, nor can types be lifted to values. This proposal only allows proper type -> type functions (we already have value -> value functions), but it's missing the other two cases. And no, typeof does not provide that ability, because it merely grabs the type of that binding, and is equivalent to using a type alias with explicit types.
a is T already exists for things like this:
interface ArrayConstructor {
    isArray(value: any): value is any[];
}

And Is<Type, Super> is a static instanceof assertion, and you can use it like this:
function staticAssert<T>() {}
declare const value: any

if (Array.isArray(value)) {
    staticAssert<Is<typeof value, any[]>>()
} else {
    staticAssert<NotA<typeof value, any[]>>()
}

@asfernandes
The reason I chose not to use a ternary is because of two reasons:

It visually conflicts with nullable types, and is also much harder to parse (you have to parse the whole expression before you know if the right side is a nullable type):
type Foo = (value is number ? string : boolean)
type Foo = (value is number? ? string : boolean)

Types may have more than two different conditions (e.g. with overloaded types), and the ternary operator doesn't make for very readable code in this case.

i suggest you list type overloads one per line (rather than all in the samr
| separated list), it's cleaner, proven to work, doesn't need 3nary
operator
On Jan 8, 2017 8:03 PM, "Isiah Meadows" notifications@github.com wrote:

@asfernandes https://github.com/asfernandes
The reason I chose not to use a ternary is because of two reasons:

It visually conflicts with nullable types, and is also much harder to
parse (you have to parse the whole expression before you know if the right
side is a nullable type):
type Foo = (value is number ? string : boolean)type Foo = (value is number? ? string : boolean)

Types may have more than two different conditions (e.g. with
overloaded types), and the ternary operator doesn't make for very readable
code in this case.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/13257#issuecomment-271195552,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA5PzZI0WDoZcUpIVQ6w65Z8dCdTSOecks5rQYdlgaJpZM4LZObU
.

@aleksey-bykov TypeScript only cares about newlines for ASI, and there's no other precedent for newline significance. Additionally, I intentionally phrased the constraint types as a union of constraints, so they could be similarly narrowed with control flow (just as current union types can be), and that's why I used the | union operator.
As for why I chose a union instead of separate type overloads, here's why:

I don't need to create a dedicated impossibility type, and can just declare any particular token as a keyword. This limits the compatibility impact and simplifies parsing greatly.

Type aliases will remain to always resolve to something, so it doesn't involve rewriting core logic that relies on this assumption. And the TypeScript code base has historically been a giant ball of mud with assumptions like these littered across the code base.

I don't have to create a type alias to define such a type every time. This not only provides flexibility (I can define one any time I want), but it also lets me create lambda return types that depend on the types of their parameters, even if they're unions or generics whose type is detected at runtime. The latter is plainly not possible with named types.

Return types can statically depend on the generic type parameter as well as the parameters themselves. This is a must for capturing and properly constraining Promise.resolve as a standalone method, since it's literally impossible to ever return a Promise<Thenable<T>> due to thenable coercion.

I did in fact already consider the idea of type overloads, and initially tried that route before posting this. The above issues, especially the first three, are why I elected to go a different route instead.

@isiahmeadows, your proposal is what I would like to see in TypeScript.
However, I do not think that this is the union. It is the ordered selection, not all alternatives together (like in PEG). And narrowing should be designed from the scratch for this kind of types.
I would like to use a / instead of | to emphasize that the order is relevant (the same intuition as PEG)

However, I wanted to move in the direction of type decomposition via switch-types
type CoerceToValue<T> = switch(T)  {
     case<V> Thenable<V>: V;
     default: T;
}

or even
type CoerceToValue<T> = switch(T)  {
     case<V> Thenable<V>: CoerceToValue<V>;
     default: T;
}

@Artazor That might work, too, but I have my reservations in terms of expressiveness. How would you do something equivalent to my Super<T> type (any supertype of T), and how would you constrain the T correctly with Promise<T> (where T cannot be a thenable)?
// Using my proposal's syntax
type Super<T> = (U in T extends U: U)
interface Promise<T extends (T extends Thenable<any>: * | T: T)

What about never as impossibility assertion?

@bobappleyard Can't use it because it's already a valid return type (specifically a bottom type, a subtype of every type).
function error(): never {
  throw new Error()
}

I need an impossibility type, where even merely matching it is contradictory.

Note to all: I updated my proposal some to aid in readability.

I'd like to solve something like https://github.com/Microsoft/TypeScript/issues/12424.
I just want to check, if I have understood this proposal correctly.
Say I have this example:
// some nested data

interface Data {
  foo: string;
  bar: {
    baz: string;
  };
}

const data: Data = {
  foo: 'abc',
  bar: {
    baz: 'edf'
  }
};

// a generic box to wrap nested data

type Box<T> = {
  value: T;
};

interface BoxedData {
  foo: Box<string>;
  bar: Box<{
    baz: Box<string>;
  }>;
}

const boxedData: BoxedData = {
  foo: {
    value: 'abc'
  },
  bar: {
    value: {
      baz: {
        value: 'edf'
      }
    }
  }
};

I'd like to express BoxedData in a generic way. Would this be correct?
// should box everything and if T is an object,
//   - it should box its properties
//   - as well as itself in a box
//   - and arbitrary deep
type Boxing<T> = [
    T is object: [P in keyof T]: Box<T[P]> & Box<T>,
    T: Box<T>,
]

type BoxedData = Boxing<Data>

@donaldpipowitch Your Boxing<T> type is almost correct.
// arrays should be boxed, too and all of the items inside of the array
type Boxing<T> = [
    T extends object: {[P in keyof T]: Boxing<T[P]> & Box<T>},
    U in T extends U[]: Boxing<U[]> & Box<T>,
    T: Box<T>,
]

Note a few changes:

variable is Type requires the LHS to be a value binding (e.g. let foo = ...), not a type binding (e.g. type Foo = ...). What you're really looking for is T extends Type.
I fixed your mapped type to use the correct syntax.
I used an existential on the array line to capture the array item type.

@donaldpipowitch Updated with my newest changes:
type Boxing<T> = [
    case T extends object: {[P in keyof T]: Boxing<T[P]> & Box<T>},
    case U in T extends U[]: Boxing<U[]> & Box<T>,
    default: Box<T>,
]

I added keywords to make it a little more readable and obvious at the cost of a little extra verbosity.

Your first set of examples are still using the old syntax
On 27 Mar 2017 16:36, "Isiah Meadows" notifications@github.com wrote:

@donaldpipowitch https://github.com/donaldpipowitch Updated with my
newest changes:
type Boxing = [
case T extends object: {[P in keyof T]: Boxing<T[P]> & Box},
case U in T extends U[]: Boxing<U[]> & Box,
default: Box,
]
I added keywords to make it a little more readable and obvious at the cost
of a little extra verbosity.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/13257#issuecomment-289491739,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AACMHAYXqhpJSdWGZnoiPmGHk2z7xIVGks5rp9d7gaJpZM4LZObU
.

@bobappleyard Thanks for the catch! Should be fixed now.

@isiahmeadows Thank you. This looks really useful for our use case. I hope this will be implemented someday ❤

that little extra verbosity finally makes it readable to a layman, such as myself. :P

Welcome.

@MeirionHughes Welcome

Looks like a great idea with a lot of immediate uses :) Any idea when this might hit production? :)

Same here, mobx-state-tree would benefit highly from this feature

@isiahmeadows
I want to write types for Telegram API Update type. Is this right types?
type XMessage = { message: Message }
type XEditedMessage = { edited_message: Message }
type XChannelPost = { channel_post: Message }
type XEditedChannelPost = { edited_channel_post: Message }
type XInlineQuery = { inline_query: InlineQuery }
type XChosenInlineResult = { chosen_inline_result: ChosenInlineResult }
type XCallbackQuery = { callback_query: CallbackQuery }

type Update<X> = [
   case X is XMessage: X,
   case X is XEditedMessage: X,
   case X is XChannelPost: X,
   case X is XEditedChannelPost: X,
   case X is XInlineQuery: X,
   case X is XChosenInlineResult: X,
   case X is XCallbackQuery: X,
   default: throw
]

const value = getUpdate()
const u: Update<typeof value> = value

@goodmind Constraint types do not resolve this. You would be interested in this proposal with disjoint types.
The expression value is Type takes a variable name on the left hand side, like in let value = 2, not a type name like in interface X {}. It's an expanded version of the existing return-only type, which similarly only accepts a parameter name, like in isArray(value: any): value is any[] within the standard library.

@isiahmeadows what is if constraint A ?

@goodmind I updated the proposal with some new types and cleaned it up quite a bit when I moved it to a gist.

Thank you for the effort. Do you know what would be the next steps to get something like this implemented?

@isiahmeadows it is sometimes cumbersome to read this gist (and Xor and Disjoint types as well). Can you add more code examples to gist?

@goodmind I'll update it with the constraint types explained better. I'll also introduce a high-level summary, to make it easier to understand.

@goodmind Updated the gist. Also, the Disjoint type was wrong (it returned the Xor result rather than a mapped case variable), so I corrected it.

Gist updated with compile-time assertions

Would this proposal allow someone to write an type/interface that represents just the readonly properties of a type?  What I mean is something like
type WritableKeys<T> = // somehow?
type ReadonlyKeys<T> = // somehow?
type WritablePart<T> = { [K in WritableKeys<T>]: T[K] };
type ReadonlyPart<T> = { [K in ReadonlyKeys<T>]: T[K] };
type Identityish<T> = WritablePart<T> & Readonly<ReadonlyPart<T>>;

so that you can write a safe version of
function unsafeSet<T,K extends keyof T>(obj: T, prop: T, val: T[K]) {
    obj[prop] = val; // what if T[K] is readonly?
}

like
function unsafeSet<T,K extends WritableKeys<T>>(obj: T, prop: T, val: T[K]) {
    obj[prop] = val;
}

Similarly for making an interface from a class, excluding any private members:
type PublicKeys<T> = // somehow?
type ProtectedKeys<T> = // somehow?
type PrivateKeys<T> = // somehow?
type PublicPart<T> = { [K in PublicKeys<T>]: T[K] };

These are constraints on types but I'm not sure if there's any way to express them.  If this is not the appropriate issue I'll find or create another one.  Thanks!

@jcalz No, because type-level property reflection is out of scope of this proposal.

Thanks.

Thanks.
EDIT: wait, couldn't you do something like
type ReadonlyPart<T> = {
    [K in keyof T]: [case ({K: T[K]} is {readonly K: T[K]}: T[K]];
}

?

@jcalz That doesn't work (for readonly), for two reasons:

The LHS of value is Type is restricted to identifiers (for now), to ease general implementation.
Read/write properties aren't soundly checked ATM (bug), and the correct behavior would have read-write subtype readonly (i.e. RW extends RO), but not vice versa.

Assuming the latter and #15534 are both fixed, you would need to do this instead:
type ReadonlyKeys<T> = keyof ReadonlyPart<T>;
type ReadonlyPart<T> = {
    // Check if not assignable to read/write.
    [K in keyof T]: [case !(T extends {[K]: T[K]}): T[K]];
};

For any other modifier (public, private, protected), it still remains impossible, because TypeScript does not expose those at all at the type level outside their scope.

I thought there was likely a way with readonly properties, but couldn't come up with one initially.

@ajbouh check conditional types PR: https://github.com/Microsoft/TypeScript/pull/21316

@ajbouh Item of note: it's really only implementing part of it. Specifically, a variant of my proposal is being implemented right now:

Conditional type (like my [case ...]): #21316
Existential type (like my [case U in ...]): #21496 (note: like mine, it's restricted to the condition part of conditional types)
Constraints as types: no issue I'm aware of*
Impossible type (my throw): no issue I'm aware of*

The third point could be easily shimmed with some boilerplate in terms of the first, but the fourth currently cannot.
As for a quick TL;DR, for those who aren't fully aware of what each one is, or how it's implemented:

Conditional type: this is like a lazy if/else, but for types. The proposal being implemented is literally a type-level ternary operator, the same conceptually as the value-oriented version you already know.
Existential type: this is your generic "for every item", but instead of you having to use any, you can still be safe about it when you pass it to another whatever, and it just works. They use infer at each use site within the condition, where I specify it outside the type.
Constraints as types: this is exactly how it sounds - T extends Whatever being equivalent to the in-progress T extends Whatever ? true : false, and the ternary just being SomeConditionalBoolean ? Foo : Bar. It hasn't been outright rejected, but the TS team has noted it would be rather difficult.
Impossible type: this is exactly what you'd expect: a type that's an error if ever evaluated. I have not received any indication, nor found/read any, from the TS team that they are for or against this, but it's a pretty natural continuation of having conditional types - you might want to conditionally reject a particular type. (Promises come to mind here - a Promise<Promise<T>> type is literally impossible.)

* TS team: if there is an issue open for either of these two, please tell me so I can edit this in.

I have been checking issues similar to this one lately.
The Impossible type seems to be tracked in #23689 and Promise<Promise<T>> is in #27711, which has a multitude of issues and pull requests associated with it.
I'm also waiting for support for upper-bound contraints (super, narrows, etc) that is not mentined here but is discussed in #9252.

Closing this issue as the TS team has basically implemented the majority of it through its conditional types, just with a different, more JS-like syntax.

authors: Artazor MeirionHughes MichaelTontchev aleksey-bykov asfernandes bobappleyard donaldpipowitch goodmind isiahmeadows jcalz leandro-manifesto mkusher mweststrate

repo: microsoft/TypeScript


text:
Use another overload signature's documented info if exact one's info is missing

TypeScript Version:  3.0.0-dev.20180522

Search Terms:
Code
/**
 * A
 */
function f(a: 0): void;
function f(a: number): void;
function f(a: number) {
}
f(1);

Expected behavior:
f(1) has documented info A.
Actual behavior:
f(1) has no documented info.
Playground Link:
Related Issues:

PRs welcomed.

This needs a little more thought than the opening post describes:
Does it only use the description or tags as well?
Should it only look at other signatures if the current signature has no jsdoc comment at all?
How should @param tags of other signatures be handled?
This may be kind of a braking change if it also uses @deprecated tag of another signature.

Duplicate of #407

source: gharchive/issue

authors: ajafff falsandtru mhegazy sandersn

license_type: permissive

license_source: github-api


text:
New Website Logo: IT.focus

Please fill the following out:

Name: IT.focus
Homepage url: https://itdotfocus.com
Brand Guidelines/Licensing: none
Logo:

Hey folks -we're looking at a new website and it's likely that the friends of TypeScript page isn't going to make it to the new site. This is mainly because close to everyone is a friend of TypeScript now and listing folks kinda feels a bit un-inclusive to everyone else.
So I'm going to close this issue - thanks for posting to apply


text:
Update contributing documentation

@RyanCavanaugh recently walked through CONTRIBUTING.md and our wiki and commented that the process is a bit old and crusty. In the interest of making things more obvious for contributors, we need to clean things up here.

I'm currently trying to get an overview of the project, including contribution etc.
The project-host (github) is not very helpful with this:

3891 issues
112 Issue-Labels in one(!) level
zero functionality for "subsystems" or "components"

Any serious issue-tracker for larger projects (like typescript is) has fields for:

Issue-Category (bug, feature, enhancement, question etc.)
Severity (on user side)
Priority (from team)
most (MOST) important: Component (or Subsystem)

Don't believe this"
Test:

Focus on the "compiler" subsystem within the typescript code.
Get notifications ONLY for src/compiler subsystem.
Follow Issues for the "compiler" subsystem.

=> you can't, because Github does not allow for this
Why? Because the early product-managers had "flat" thinking, and the masses were fine with it.

An excellent system need zero documentation, because it's self-documenting.
But! A system full of weaknesses and flaws needs many documentation.
Fix those very fundamental github weaknesses, then start to write contributor-documentation.
4000 issues, 113 labels, seriously, you don't see the usability disaster here?
.

authors: DanielRosenwasser lazaridiscom


text:
No information for Error: Debug Failure. No error for last overload signature

TypeScript Version:  3.7.2

Search Terms:
Debug Failure, No error for last overload signature, Typescript 3.7.2, Sonar
Code / Error
Code is not available - executing entity is sonar runner
As well formatted image

or as code...
Analyzing 292 typescript file(s) with the following configuration file /jenkins/workspace/Viper/Nova-Web/trunk/nova/packages/Nova/nova-app/tsconfig.json
00:20:19  00:20:18.347 ERROR - /jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:2137
00:20:19  00:20:18.347 ERROR -             throw e;
00:20:19  00:20:18.347 ERROR -             ^
00:20:19  00:20:18.347 ERROR -
00:20:19  00:20:18.347 ERROR - Error: Debug Failure. No error for last overload signature
00:20:19  00:20:18.347 ERROR -     at resolveCall (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:55202:38)
00:20:19  00:20:18.348 ERROR -     at resolveCallExpression (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:55548:20)
00:20:19  00:20:18.348 ERROR -     at resolveSignature (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:55904:28)
00:20:19  00:20:18.348 ERROR -     at getResolvedSignature (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:55935:26)
00:20:19  00:20:18.348 ERROR -     at getContextualTypeForArgumentAtIndex (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52352:118)
00:20:19  00:20:18.348 ERROR -     at getContextualTypeForArgument (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52347:50)
00:20:19  00:20:18.348 ERROR -     at getContextualType (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52718:28)
00:20:19  00:20:18.348 ERROR -     at getApparentTypeOfContextualType (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52620:17)
00:20:19  00:20:18.348 ERROR -     at getContextualSignature (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52924:24)
00:20:19  00:20:18.348 ERROR -     at getContextuallyTypedParameterType (/jenkins/workspace/Viper/Nova-Web/trunk/nova/node_modules/typescript/lib/typescript.js:52200:39)
00:20:19  00:20:18.390 ERROR - External process `node --max-old-space-size=2048 /jenkins/workspace/Viper/Nova-Web/trunk/nova/packages/Nova/nova-app/.sonar/sonarts-bundle/node_modules/tslint-sonarts/bin/tsrunner` returned an empty output. Run with -X for more information

Expected behavior:
Should give some additional information what the problem is
Actual behavior:
When looking at the error, I have no idea if it's an issue with my application code, with sonar or with typescript itself

It's a crash, so by definition something has broken in an unexpected way 😢
Some code snippet that would reproduce this crash would be extremely helpful - would you be able to share an example? We might be able to deduce what went wrong from staring at the code, but it takes a lot longer

So we use TS 3.7.2 and are getting this error while using @mangoweb/scripts-base v0.0.12
We hit this error when we try to initialize a class which extends our Component.ts

@RyanCavanaugh I made a minimal test case for our version of Debug Failure Error: https://github.com/enzy/ts-scriptsbase-debug-failure

I have another minimal repo for this, with typescript 3.8.3 and @apache-arrow/ts
src/test.ts
import { Table } from "@apache-arrow/ts";

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./dist/"
  }
}

I had this with the latest version of TypeScript (currently 4.3.2), but setting the "includes" property in tsconfig.json removed the issue.

I have encountered this issue in TypeScript 4.4.3, I don't know if further examples are wanted but this minimal repro may be useful since it's standalone (no packages); the error seems to occur no matter the tsconfig options, I tested that it still occurs with no tsconfig at all.
interface CollectionDocument<TIdPrefix extends string> {
	id: `${TIdPrefix}_${string}`;
}

type CollectionDocumentIdPrefix<TCollectionDocument extends CollectionDocument<string>> =
	TCollectionDocument["id"] extends `${infer TIdPrefix}_${string}` ? TIdPrefix : never;

type CollectionSpecs = { [name: string]: CollectionDocument<string>; };

type CollectionSpecNames<TCollectionNames extends string> = TCollectionNames | `History_${TCollectionNames}`;

interface HistoryDocument<TDocument extends CollectionDocument<string>> extends CollectionDocument<`hist_${CollectionDocumentIdPrefix<TDocument>}`> {
	document: TDocument | null;
}

type CollectionFromName<
	TCollectionSpecs extends CollectionSpecs,
	TCollectionName extends CollectionSpecNames<keyof TCollectionSpecs & string>,
> =
	TCollectionName extends `History_${infer TOriginalCollectionName}`
		? Collection<HistoryDocument<TCollectionSpecs[TOriginalCollectionName]>>
		: Collection<TCollectionSpecs[TCollectionName]>;

class Driver<TCollectionSpecs extends CollectionSpecs = CollectionSpecs> {
	public getCollection<TCollectionName extends CollectionSpecNames<keyof TCollectionSpecs & string>>(): CollectionFromName<TCollectionSpecs, TCollectionName> {
		// This line seems to be the origin of the error, the 'this' argument specifically
		return new Collection<CollectionDocument<string>>(this) as any;
	}
}

class Collection<TDocument extends CollectionDocument<string>> {
	public driver: Driver;
	public document: TDocument;

	public constructor(driver: Driver) {
		this.driver = driver;
	}
}

An other example:
versions:
typescript: 4.5.5 and 4.7.0-dev.20220218
mongodb: 4.4.0
import { Collection } from 'mongodb';
import type { OptionalUnlessRequiredId } from 'mongodb';

export type MongoDocument<T> = OptionalUnlessRequiredId<Omit<T, 'id'> & { _id: string }>;

export type MongoDocumentWithPartialId<T> = OptionalUnlessRequiredId<Omit<T, 'id'> & { _id?: string }>;

export declare function toProjectedEntity<T extends Entity>(document: MongoDocumentWithPartialId<T>): any;

export class MongoBaseRepository<T extends Entity> {
  readonly collection: Collection<any>;

  async loadManyProjectedByFilter(): Promise<any> {
    const documents = await this.collection.find<MongoDocument<T>>({}).toArray();
    return [documents.map(toProjectedEntity)];
  }
}

Only happens if Entity is an non existing type.

The point about this issue should be to emit more detailed feedback whenever it happens, so we can troubleshoot it by ourselves.
This other issue has a suggestion about how to do that:
https://github.com/microsoft/TypeScript/issues/33133#issuecomment-526277334
It would already be a great improvement, but if it were also possible to retrieve the file/line where the call happened, it would be perfect.

authors: Renatopster RyanCavanaugh bagbag bene-starzengruber enzy ksabry pprice tuomokar


text:
When using generic parameters, the actual type is not assignable to an InstanceType on a constructor in an interface

I'm pretty sure this is a bug:
As there aren't generic namespaces, I'm trying to leverage constructors being passed for their types and not just their values.
I'm doing this using the InstanceType type, and it looks like there are cases where there is difference in behaviour between a direct value, a constructor, using attribute type lookup ([] on a type) and using typeof on a value.

TypeScript Version:  Nightly, 3.8.3 (tested in playground)

Search Terms:
InstanceType
constructor
Code
class SomeClass {}

interface Factory<T> {
    make: { new(): T }; // This is a constructor for "T"
    value: T;
}

const factory: Factory<SomeClass> = { make: SomeClass, value: new SomeClass() };
const works1: SomeClass = new factory.make();
const works2: InstanceType<Factory<SomeClass>['make']> = new factory.make();
const works3: InstanceType<(typeof factory)['make']> = new factory.make();

function doesntWork<T, TFactory extends Factory<T>>(factory: TFactory): void {
    const works1: T = new factory.make();
    const valueWorks: TFactory['value'] = factory.value;

    const doesntWork2: InstanceType<TFactory['make']> = new factory.make();
    const doesntWork3: InstanceType<(typeof factory)['make']> = new factory.make();
    const doesWork: InstanceType<typeof factory.make> = new factory.make();
}

Expected behavior:
works1, valueWorks, doesntWork2, doesntWork2 and doesWork should all validate.
doesntWork2 and doesntWork3 should be assignable. (Similar ones work outside the function)
If my analysis is wrong, and they are not - the error message should be more clear.
Actual behavior:
works1, valueWorks and doesWork validate.
For doesntWork2: Type 'T' is not assignable to type 'InstanceType<TFactory["make"]>'
For doesntWork3: Type 'T' is not assignable to type 'InstanceType<TFactory["make"]>'
Playground Link:
https://www.typescriptlang.org/play/?ts=3.9.0-dev.20200328&ssl=1&ssc=1&pln=20&pc=2#code/MYGwhgzhAEDKD2BbApgYXFaBvAvgWAChCBLAOwBdkAnAMzGGWgDF7z4qBPAHgBUA+bIWjDoiMAGtkALmzRSyAO4AKAJQye0HAG5oAel3QeAC2IxT0MNGDxSEclQCuwNlWg120AEQ9PQkQDcwEAdpQy1CfCICa1tyN1Z2DhkWZ0SuBBR0SAgBAF5ZMUkZDLQMCAAaaEDg0PkFOCRS7NVNcOibO2gFdnEIAEZixqzMfLr41M4AOkLkVTaYzu6qXoAmGQBJWLBSBh4OAAdkLhSXbhLhnIBtAHIZ64BdPLlFcdPpiVmVeY64pd6AZg2Wx2yD2hy4SnIB2Q8Bor0SKhud0e0FGLzoEw470kc0IhBoDh25GINmgABN4MgIBQAOo9XiVHgnRLQZAAD0opDJMGZnF4fD4Sgxp3UvI4aiq8GIZMEBBEVh+XR6-XUqOe9WFiWxnza8oWcWqITpywgooSnBuhuQDzVmqmVrafmE+vJlOp5GN4jW0E2dm2u2hvDFSI+DyeYztWJmuLlIhdFKptJ6gJ9wID4Mh0Nh8M4iNuoZRaI15qjHxjesVCYgnqBfpBYKOUMO2cj2vD6JL2pjOCAA
Related Issues:
https://github.com/microsoft/TypeScript/issues/34565 (Uses this, not a generic parameter)

Lookup types on generic type parameters are fully deferred - T["prop"] is effectively an opaque thing, and a conditional type like InstanceType can't match an infer T to it. In general this limitation doesn't produce many completeness deficits; attempts to assign some concrete value to a T["prop"] are unlikely to be sound against aliasing or manual type parameter specification.
There are only a few cases where it's provable from the outside that the assignment is safe - this is one of them - but we'd have to do a ton of special casing throughout the type system to make these work, and it's not common enough to justify the needed complexity.

Thanks for the quick response Ryan! The rationale makes total sense. (And I'll use the opportunity to say I ❤  TS and thank you)
It may be helpful to have a better error message, as the current one makes it seem that the types are not assignable, where it is actually an TS implementation limitation, but probably not high priority as you say it's not a common case.
Two follow up questions:

I haven't opened many issues in OS projects. As this is a known design limitation, should I close the issue? Or keep open for future / people looking for open issues?

(This might be more a question for SO, and if it is feel free to let me know and I'll post there instead) Given lookups for generics are fully deferred, is there a way to have a "type namespace" which isn't fully deferred? I'll give an example:

interface MyTypeGroup<A,B keyof A,C> {
    aThing: Required<A>;
    bThing: Pick<A,B>;
    cThing: Parameters<C>;
}

// Then,
function func<M>(a: M['aThing'], b: M['bThing']) {
}

There purpose would be to be reduce the verbosity of template arguments required in situations with lots of inter-dependent generics. Currently I put together a type alias for each of the "aThing", "bThing", etc separately, but it ends up very verbose as I need to specify the template params for each (imagine its 8 params, some of which are complex).
I hope this make sense, and thank you.

Open/close state is up to the project maintainers to define. For us, "open" means "actionable work exists", and there's no actionable work here, so this will get automatically closed at some point in the future.
In this situation there's not much from the type system we can "see" to be able to identify a better error message, I think. For a lot of cases with generics we can check relative to the constraint, etc, but this is more of a counterfactual reasoning thing where if the type hadn't been deferred, then something else would have happened, but this requires sort of redoing the entire operation with different rules in place.
I'm not quite sure what you're trying to do with that example. An SO post with more examples would probably get useful answers pretty quickly from some of our stellar helpers out there - if not, ping me on Twitter @SeaRyanC and I'll go take a look.

Thanks.
My thinking RE the type system, is - its figuring out assignment can't happen, but it gives no reason. Going out on a limb here, In the underlying code where the fact that it is not assignable is discovered - could there be a way to share why?
Re the example, will take to SO. Thank you!

Another situation where I think this problem is rearing its head (for future readers):
const fruit = {
    apple: { color: () => 'red' as const },
    banana: { color: () => 'yellow' as const }
}
type Fruit = typeof fruit
type FruitKeys = keyof Fruit
function getFruit<T extends FruitKeys>(key: T): ReturnType<Fruit[T]['color']> {
// Type '"red" | "yellow"' is not assignable to type 'ReturnType<{ apple: { color: () => "red"; }; banana: { color: () => "yellow"; }; }[T]["color"]>'.
//   Type '"red"' is not assignable to type 'ReturnType<{ apple: { color: () => "red"; }; banana: { color: () => "yellow"; }; }[T]["color"]>'.
    return fruit[key].color()
}

It is useful to note that if we move the inference to the call site the problem goes away:
function getFruit<T extends FruitKeys>(key: T): Fruit[T]['color'] {
// Type '"red" | "yellow"' is not assignable to type 'ReturnType<{ apple: { color: () => "red"; }; banana: { color: () => "yellow"; }; }[T]["color"]>'.
//   Type '"red"' is not assignable to type 'ReturnType<{ apple: { color: () => "red"; }; banana: { color: () => "yellow"; }; }[T]["color"]>'.
    return fruit[key].color
}
getFruit('apple')()

authors: MicahZoltu RyanCavanaugh hochbergg


text:
Narrowed types do not flow into callback functions

Bug Report
Previous discussion https://github.com/microsoft/TypeScript/issues/37255#issuecomment-779665895
Title is borrowed from @danielrentz https://github.com/microsoft/TypeScript/issues/37255#issuecomment-779668433  I don't know if its accurate description of the problem.
🔎 Search Terms
None
🕗 Version & Regression Information
Any
⏯ Playground Link
Playground
💻 Code

import { FunctionComponent, useMemo } from 'react'

export interface ButtonProps {
  size?: 'sm' | 'base' | 'lg'
}

export const Button: FunctionComponent<ButtonProps> = props => {
  props.size ??= 'base'
  const sizeClassNames = useMemo(() => {
    return {
      sm: 'px-3 py-2 text-sm',
      base: 'px-4 py-2 text-sm',
      lg: 'px-4 py-2 text-base'
    }[props.size] // << Type 'undefined' cannot be used as an index type.(2538)
  }, [props.size])

  return (
    <button
      type="button"
      className={sizeClassNames}
    >
      Button text
    </button>
  )
}

🙁 Actual behavior
Type 'undefined' cannot be used as an index type.(2538)
🙂 Expected behavior
props.size should not be considered as undefined

Another duplicate of #9998.

authors: MartinJohns kolpav


text:
Suggestion: Iterate through Enum values

Enums currently get outputted to an object with two-way mapping of numbers. This makes it hard to iterate through the names (or values) of an enum. A method on the enum object to get the keys of the enum would allow iterating.
See this StackOverflow question for a use case of iterating. (And use of a regular expression for filtering).
Possible Solutions:

Add a length property (for enums with default index) too limited
Function on enum type filtering keys looking for numbers (could break with other index types)
Add a function with the keys hard coded when compiling

Complications:

User defined indexing
Negative index numbers
Proposals for other index types (#3192, #1206, #2491)

I don't think this is a common enough case to emit such a helper for all enums that every TypeScript user writes.
Note that you can merge modules and enums to add methods to the enum yourself if you really do need this functionality. For example, using ES6 generators you can achieve something close to what you want:
enum E {
	A = 2,
	B = 4,
	C = 6
}

module E {
	export function* getvalues() {
		yield E.A;
		yield E.B;
		yield E.C;
	}
}

for(var i of E.getvalues()) {
	console.log(i);
}

Okay, thanks for the suggestion. I'll see if that is a suitable solution.

Seems like it would be a common use-case to me. I certainly would like that included automatically.

It is a common case, for example, you may want to generate a dropdown list from enum dynamically. It is easy to implement too, just add length property to the enum.
(function (MyOptions) {
    MyOptions[MyOptions["option1"] = 0] = "option1";
    MyOptions[MyOptions["option2"] = 1] = "option2";
    MyOptions.length = 2;
})(MyOptions || (MyOptions = {}));

I don't understand the argumentation to not include this at all. Too complex maybe, but not a common use case?
What other language has enums and no way to iterate over them?

no way to iterate over them?

You can iterate over them. See http://stackoverflow.com/a/18112474/1704166 .

@RyanCavanaugh
Thank you that does work. My mistake - I misunderstood this issue.

@danquirk Can't compiler just emit the same code?
It is really sad it's not supported, as every other language with enums have the functionality

Please don't show up with noise comments.

It seems that the enum is undefined at runtime in files other than where it was declared so I can't enumerate over the enum using Object.keys.

Well, generally how else are people able to show their support but by making some noise for the cause?
This issue is rank 4 on DuckDuckGo and 3 on Google when searching "typescript iterate enum" (which is how I got here as well). I guess wanting to iterate over enums is not an uncommon use case after all and both solutions that were brought up in here are essentially workarounds and quite bulky.

TypeScript isn't going to emit additional code for every enum just to enable you to do something you can already do by writing code in userland. All the data you need is present at runtime; there's no need for it.

I guess by going down that thought we should all be writing and compiling our own assembly code since everything is technically already possible there? /j
I think asking "Can it work without the new feature?" is the wrong approach. The main purpose of a programming language is to make it easy for people to produce solutions. If this new feature accomplishes this, is intuitive (Because let's face it: Both solutions are not unless you are knee deep in the specs) and comes at a reasonable cost: Why not?
There are many examples of "sugar" in JS, basically the whole Array methods are. So forgive me for asking but why is it such a big deal for TS to add aditional functionality? I'm guessing the third part of my before mentioned feature requirements is the problem?

I want to add one more technical point. One suggested approach is http://stackoverflow.com/a/18112474/1704166. The problem with it is that it doesn't iterate over values in a type-safe manner - it will produce numbers or strings. So downstream of iteration type safety is lost.
I believe a lot of people who need the iteration are lead to that approach and that's bad. @danquirk's solution is fine and I want to give credit to it.
As for philosophical debate, I think a lot of people who are coming to Typescript from other languages, while in awe of other language features, are left wondering about enum support. Enums in Typescript are not on par with other high-level languages. Personally I don't care what it is compiled down into, as long as it behaves like I expect from an enum type. Maybe it should be reassessed if the right compromise was made between enum usefulness and complexity of the generated code.

For easy and useful approaches, that haven't managed to bog down runtimes, have a look at Java: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html.  Or Python: https://docs.python.org/3/library/enum.html.
To me, there is nothing philosophical about current support for enum iteration in Typescript.  It is just broken.  It doubles the number enum values, present each one twice: once for the name, and again for the value.   There's no clear cut way to distinguish between names and values.  Nor any guarantee of order in the language (could break with any TS update).   There's no philosophy there to defend.  Just a misunderstanding of what enumerated types mean in any scripting language (e.g. Java, Python, ...).
A practical issue I am having is how to deserialize values from the server (via JSON) into actual enum values in my Typescript code.   Some evil hack may work yet.  But it really should be easy to iterate through enum instances, compare the given value to either the name or value and, if I have a match, use the current enum instance.   Currently, this direct approach is not possible.
    System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass));
}```

Not so common use case (?):
enum QueueEvents {
  ITEM_PUSHED = 'item_pushed',
  ITEM_POPPED = 'item_popped'
}

class Queue {
  private readonly eventEmitter: EventEmitter = new EventEmitter();

  // some linked list implementation here

  on(event: QueueEvents, listener: (...args: any[]) => void) {
    this.eventEmitter.on(event, listener);
  }
}

Now let's iterate the QueueEvents (in some unit test):
const queue = new Queue();

for (let event in QueueEvents) {
  queue.on(event, () => console.log('emitted ' + event));
}

Doesn't work since event is a string here not a QueueEvent.

example here:

function enumToArray<T>(t: T): ReadonlyArray<T[keyof T]> {
  const values = Object.values(t);
  return values.some(x => typeof x === 'number')
    ? values.filter(x => typeof x === 'number')
    : values;
}

enum PlayType {
  tragedy = 1,
  comedy = 2,
}

/**
 * @type readonly PlayType[]
 * @value [1, 2]
 */
const PlayTypeList = enumToArray(PlayType);

enum PlayType2 {
  tragedy = 'tragedy',
  comedy = 'comedy',
}

/**
 * @type readonly PlayType2[]
 * @value ['tragedy', 'comedy']
 */
const PlayTypeList2 = enumToArray(PlayType2);

example here:
function enumToArray<T>(t: T): ReadonlyArray<T[keyof T]> {
  const values = Object.values(t);
  return values.some(x => typeof x === 'number')
    ? values.filter(x => typeof x === 'number')
    : values;
}
[ ... snip ... ]
const PlayTypeList2 = enumToArray(PlayType2);

Doesn't work since members of the array are strings or numbers here, not enums.  For example, you can't pass them to a function expecting an array of enum values.

Update:
function enumEntries<T>(t: T): ReadonlyArray<readonly [keyof T, T[keyof T]]> {
  const entries = Object.entries(t);
  const plainStringEnum = entries.every(
    ([key, value]) => typeof value === 'string'
  );
  return (plainStringEnum
    ? entries
    : entries.filter(([k, v]) => typeof v !== 'string')) as any;
}

function enumKeys<T>(t: T): ReadonlyArray<keyof T> {
  return enumEntries(t).map(([key]) => key);
}

function enumValues<T>(t: T): ReadonlyArray<T[keyof T]> {
  const values = Object.values(t);
  const plainStringEnum = values.every(x => typeof x === 'string');
  return plainStringEnum ? values : values.filter(x => typeof x !== 'string');
}

can enum with number values compile like this :
const Direction = {
  Left: 0,
  Right: 1,
  Down: 2,
  Up: 3,
  '__proto__': {
    0: 'Left',
    1: 'Right',
    2: 'Down',
    3: 'Up'
  }
};

i have a babel plugin test it babel-plugin-iterable-enum

@houfeng0923 I like the looks of that.  Nice idea pushing the reverse mapping into the __proto__ space.

I figured I might as well share what I did in order to iterate over enums.
This is probably not the most efficient or elegant way to do this, but it yields values with the correct type, works with both numeric and string enums, is pretty short/straightforward and works for me:
function enumValues<T extends string>(enumObj: { [ key: string ]: T }): IterableIterator<T>;
function enumValues<T extends string | number>(enumObj: { [ key: string ]: T }): IterableIterator<Exclude<T, string>>;
function* enumValues<T>(enumObj: { [ key: string ]: T }): IterableIterator<T> {
  let isStringEnum = true;
  for (const property in enumObj) {
    if (typeof enumObj[property] === 'number') {
      isStringEnum = false;
      break;
    }
  }
  for (const property in enumObj) {
    if (isStringEnum || typeof enumObj[property] === 'number') {
      yield enumObj[property];
    }
  }
}

// use like this; string enums should work too
enum MyEnum { foo, bar, baz }
for (const value of enumValues(MyEnum)) {
  console.info(value); // value is of type MyEnum
}

authors: AlexLeung CharlieReitzel CorayThan RyanCavanaugh Ticmea aciccarello alamothe bladepan danquirk houfeng0923 newlukai npiv saenglert xiaoxiangmoe


text:
Google feedback on TS 4.8-beta

This GitHub issue contains feedback on the TS 4.8-beta release from the team that is responsible for keeping Google's internal software working with the latest version of TypeScript.
Executive summary

Some changes to our TypeScript code are required to make it compile with TS 4.8.
Detail sections below explain the changes to our code we expect to make to unblock the upgrade.

Impact summary

Change description
Announced
Libraries affected

Unconstrained Generics No Longer Assignable to {}
yes
0.058%

lib/d.ts changes
yes
0.013%

Improved Intersection Reduction, Union Compatibility, and Narrowing
yes
0.009%

Errors When Comparing Object and Array Literals
yes
0.006%

Unclassified
-
0.003%

The Announced column indicates whether we were able to connect the observed change with a section in the TS4.8-beta announcement.
The following sections give more detailed explanations of the changes listed above.
Changes which were announced
Unconstrained Generics No Longer Assignable to {}
We see type errors similar to the ones mentioned in the release announcement.
We expect to add extends {} to generic type parameters to fix these issues.
lib/d.ts changes
We support the typing improvements. Generally it's clear what's changing.
These are the most common errors we observed:

decorators has been merged with modifiers on the declarations that support decorators.

ReadableStreamDefaultReadResult has changed to ReadableStreamReadResult

visualViewport is nullable

We expect to add casts to any to silence the error and apply proper fixes over time.
Improved Intersection Reduction, Union Compatibility, and Narrowing
We see type errors related to unknown, NonNullability<T> due to the changes mentioned in release announcement.
We expect to add relevant type cast to fix the issues.
Errors When Comparing Object and Array Literals
We see type errors similar to the ones mentioned in the release announcement.
We expect to add casts to any to silence the error and apply proper fixes over time.

ReadableStreamDefaultReadResult has changed to ReadableStreamReadResult

I also encountered this and didn't see anything mentioned in the release notes, so I'm grateful I found this issue. Would be nice to have these kinds of type changes called out in the future.

Would be nice to have these kinds of type changes called out in the future.

This is part of the "lib updates"; correctness updates here are generally not considered noteworthy. Was there a false positive?

Would be nice to have these kinds of type changes called out in the future.

This is part of the "lib updates"; correctness updates here are generally not considered noteworthy. Was there a false positive?

Ah understood, I think in general it's not noteworthy. I think this specific issue had some churn because the streams definition was missing in a prior version, then added with the incorrect name, and then fixed in this version. https://github.com/microsoft/TypeScript/issues/42970

authors: RyanCavanaugh frost-cy johnBartos


text:
Type narrowing in one case statement does not propagate to the next case

🔎 Search Terms

Type narrowing
Switch statement

🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about switch statements and type narrowing.

⏯ Playground Link
https://www.typescriptlang.org/play?ts=5.3.0-beta#code/GYVwdgxgLglg9mABMOcAUBDATgcwFyIDOUWMYOiAPouACYCmwZ9tAlIgN4BQivRA7jCgQAFojQkQ9dtz5zEEDIXqJsFALyaaYBkzAs8Pecagiscfon2WAolnNY0rANxcjxxctW4AdMWxQhADqQiJoAEQAHuGsBAD0cYj09nBYiAAqAMoAjAAcAAwALLkEAORqpYgwhIgADnCEhDAARgA2AJ6IpXSMzLSlPu7GfFj0UCBYSOEAguGuQ3K6GCCtUIbD8qPjk4jhAEJzQwC+XCdAA
💻 Code
function foo(arg: string | undefined) {
    switch (true) {
        case arg === undefined:
            throw new Error();

        case arg.startsWith("x"): // error TS18048: 'arg' is possibly 'undefined'.
            return "A";

        default:
            return "B";
    }
}

🙁 Actual behavior
error TS18048: 'arg' is possibly 'undefined'. in the second case.
🙂 Expected behavior
I expect the type to be narrowed to string in the second case statement.
Additional information about the issue
See also #56352. Ping @Andarist.

I feel dirty seeing this code.

Forgive me if this comes off weird, but do you actually write code like that?

Forgive me if this comes off weird, but do you actually write code like that?

No. I was just trying to reduce this to a minimal example that still reproduces the same behaviour. The original code was a bit more sane. :-)

That being said, you guys started this whole thing by suggesting the switch (true) pattern in the 5.3 release notes. 😉

"suggesting" is a strong term 😄
At best, MDN has examples of it and some projects use it in lieu of pattern matching.
In any case, these issues are at least exposing that our CFA doesn't actually flow between case expressions, which was true before.

I'm having a similar issue with this code playground:
const reA = /^A(\d+)$/;
const reB = /^(\d+)B$/;

function f(line: string): number {
    let m: RegExpExecArray | null | undefined;
    switch (true) {
        case !!(m = reA.exec(line)): {
            return m![1].length;
        }
        case !!(m = reB.exec(line)): {
            return m![1].length;
        }
    }
    return -1;
}

This code works in TypeScript 5.2.
After upgrading to TypeScript 5.3, the compiler gives error "Property 'length' does not exist on type 'never'." because it somehow thinks the m in second case is never.
If I declare a separate variable m2 of same type and assign to that in the second case, the code works.

Forgive me if this comes off weird, but do you actually write code like that?

I actually wrote code like this, real code.
switch (true) is a common pattern in Go programming language, and I brought it to TypeScript.

I don't think that's directly related, but a new bug with the new implementation and probably deserves its own issue.

I think there is a much less exotic situation where this issue manifests: accidental duplicate case constants.
function f(x: "a" | "b"){
    switch (x) {
        case "a": break;
        case "a": break;  // no error ☹
        case "b": break;
    }
}

If narrowing after switch cases worked correctly, the type of x would narrowed to "b" after the first branch, and the second branch would be a type error.
For comparison, the equivalent else-if chain behaves as expected:
if (x === "a") {
    ...
} else if (x === "a") {  // error 🙂
    ...
} else if (x === "b") {
    ...
}

Here is another example:

function isHello(value: string): boolean {
        return value === "Hello";
}

function isHi(value: string): boolean {
        return value === "Hi";
}

function isUndefined(value: any): value is undefined {
        return typeof value === "string";
}

function isGreeting(value?: string): boolean {
        switch (true) {
                case isUndefined(value): return false;
                case isHello(value): return true;
                case isHi(value): return true;
                default: return false;
        }
}

// without switch case

function isGreetingIf(value?: string): boolean {
        if (isUndefined(value)) {
                return false;
        }
        if (isHello(value)) {
                return true;
        }
        if (isHi(value)) {
                return true;
        }
        return false;

}

Note: In the real world the conditions are errors checking and the returned value, an enum of the corresponding error.

Forgive me if this comes off weird, but do you actually write code like that?

I do think there are situations where a switch(true) expression can make the code a lot more readable. Random real world code example where I just stumbled over this TS bug:
Before:
    if (!fileKind) {
      return [false, `We cannot deal with file type '${mimeType}'.`];
    }

    if (this.allowedFileKinds === 'all') {
      return VALID;
    }

    if (!this.allowedFileKinds.includes(fileKind)) {
      return [false, `We cannot deal with file type '${mimeType}'.`];
    }

After:
    switch (true) {
      case !fileKind:
        return [false, `We cannot deal with file type '${mimeType}'.`];
      case this.allowedFileKinds === 'all':
        return VALID;
      case !this.allowedFileKinds.includes(fileKind):
        //                                 ^? Not inferred to be truthy!
        return [false, `We cannot deal with file type '${mimeType}'.`];
      default:
        return VALID;
    }

authors: JosXa MartinJohns RyanCavanaugh Vlad-Shcherbina Xample jakebailey johan13 yoursunny


text:
Normative changes to decorator "extra initializer" evaluation order

Acknowledgement

[X] I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.

Comment
Per https://github.com/pzuraq/ecma262/pull/12/files, which achieved consensus in the November 2023 TC39 meeting, the "extra initializers" for fields/auto-accessors (added by context.addInitializer) now need to be run independently for each field, immediately after the field itself is initialized and defined on the class instance.
This results in the need to change our emit for Stage 3 decorators as follows:
Given:
class C {
  @dec a;
  @dec b;
  @dec f() { }
}

We currently emit (some parts elided):
let C = (() => {
  ...
  return class C {
    static {
      ...
      __esDecorate(null, null, _f_decorators, { ... }, null, _instanceExtraInitializers);
      __esDecorate(null, null, _a_decorators, { ... }, _a_initializers, _instanceExtraInitializers);
      __esDecorate(null, null, _b_decorators, { ... }, _b_initializers, _instanceExtraInitializers);
      ...
    }
    a = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _a_initializers, void 0));
    b = __runInitializers(this, _b_initializers, void 0);
    f() { }
  };
})();

Here, we collect all "instance extra initializers" in a single array and evaluate them immediately after the this value is bound in the constructor (i.e. immediately upon entry to the constructor in a base class, or immediately after super() is called in a derived class). When fields are present, we evaluate the extra initializers as part of evaluating the initializer for the first field of the class.
After this change, we need to emit something like this instead:
let C = (() => {
  ...
  let _a_extraInitializers = [];
  let _b_extraInitializers = [];
  return class C {
    static {
      __esDecorate(null, null, _f_decorators, { ... }, null, _instanceExtraInitializers);
      __esDecorate(null, null, _a_decorators, { ... }, _a_initializers, _a_extraInitializers);
      __esDecorate(null, null, _b_decorators, { ... }, _b_initializers, _b_extraInitializers);
    }
    constructor() {
      __runInitializers(this, _b_extraInitializers);
    }
    a = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _a_initializers, void 0));
    b = (__runInitializers(this, _a_extraInitializers), __runInitializers(this, _b_initializers, void 0));
    f() { }
  };
})();

Here, we still run the extra initializers for methods/getters/setters first, but we run the extra initializers for a after it is defined on the instance, but before we initialize b, and run the initializers for b at the top of the constructor, which is evaluated after b has been defined on the instance.

What are "extra initializers"?  In the example code given there is no initialization at all as far as I can tell.

In the example code, a and b are initialized to undefined (i.e., void 0), which you can see in the fragment __runInitializers(this, _a_initializers, void 0). These are "normal" initializers, which decorators can hook:
function dec(target, context) {
  if (context.kind === "field") {
    return function (value) { return value; }; // injects a transformation into "normal" initialization.
  }
}

Extra initializers are added by a decorator via context.addInitializer, and are primarily meant to perform some kind of registration using the instance:
function dec(target, context) {
  context.addInitializer(function() {
    registerThisInstance(this);
  });
}

Here's an example of the difference in timing:
class C {
  @dec a = 1;
}
function dec(target, context) {
  context.addInitializer(function() {
    this.a; // before: undefined
            // after: 2
  });
  return function (value) {
    this.a; // before/after: undefined
    value; // 1
    return value + 1;
  };
}

authors: fatcerberus rbuckton


text:
sudo apt update vs sudo apt upgrade to update packages in Ubuntu/WSL

Is your feature request related to a problem? Please describe.
I am extremely new to everything computer, so maybe it's not a thing, and it's not exactly a problem. When I was updating my ubuntu package I just had to run:
sudo apt update
Then also
sudo apt upgrade
The first seemed to download the updates, and the second actively installed them? Only the first one was mentioned in the instructions at:
https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps
Describe the solution you'd like
Either add a step for upgrading or (if someone has a couple minutes to reply) tell me why what I did was unnecessary or harmful.
Describe alternatives you've considered
I have considered that I'm new to all this and maybe implementing a googled solution before asking here was a mistake, but it appeared to work so weeeeeeee
Additional context
You guys do wonderful work here and without it I'd be lost.

The apt command is a powerful command-line tool, which works with Ubuntu’s Advanced Packaging Tool (APT). The commands contained within apt provide the means for installing new software packages, upgrading existing software packages, updating the package list index, and even upgrading the entire Ubuntu system.
Some examples of popular uses for the apt utility include:
1.Update the package index
The APT package index is essentially a database of available packages from the repositories defined in the /etc/apt/sources.list file and in the /etc/apt/sources.list.d directory. To update the local package index with the latest changes made in the repositories, type the following:
sudo apt update
2.Upgrade packages
Installed packages on your computer may periodically have upgrades available from the package repositories (e.g., security updates). To upgrade your system, first, update your package index with sudo apt update, and then type:
sudo apt upgrade
Thus this two command are strictly followed while updating ubuntu packages

@DaftBucket apt update and apt upgrade are strictly functions of the Ubuntu OS package manager and not WSL. Several Linux distros use different package managers with different options to update & upgrade packages.

You already got 2 answers that you can learn.
I will explain to you now why the guide at learn.microsoft.com is as it is.

When you run sudo apt update your system will get the latest information for gnome-text-editor.
Let's say hypothetically you ran sudo apt update 1 month ago and gnome-text-editor was version 1.2 at the time.
Your system now knows the link to version 1.2.
Yesterday the gnome-text-editor version 1.4b was released for Ubuntu and the distribution servers have the newest version.
Your system doesn't know that there is 1.4b.
You run sudo apt update today and now your local repository (and the apt system) knows that the newest version is 1.4b and where to get it.
So you run sudo apt install gnome-text-editor -y and apt installs 1.4b for you.
If you hadn't run sudo apt update, the system would have installed 1.2 because that's the info it had before you ran the apt update command under sudo.
Here is a good summary and probably the better page to ask Ubuntu questions that are not related to WSL:
https://askubuntu.com/a/1426570
If you want to learn more about Ubuntu, digitalocean sometimes has some well written step-by-step guides.
Search the internet for ubuntu digitalocean. I am sure there are some good YouTubers too.

Thank you all so much for your replies, I will absolutely follow up with the resources you have provided.
I have much to learn and now a great place to start! Be well, guys!

authors: DaftBucket SHREYASH96OG iamexe zcobol

repo: microsoft/WSL

license: MIT


text:
Can no longer open a second terminal / instance

Windows Version
Microsoft Windows [Version 10.0.19045.3930]
WSL Version
Invalid command line option: --version
Are you using WSL 1 or WSL 2?

[X] WSL 2
[ ] WSL 1

Kernel Version
5.10.102.1
Distro Version
Ubuntu-20.04
Other Software
Full output of wsl.exe --status:
Default Distribution: Ubuntu-20.04
Default Version: 2

Windows Subsystem for Linux was last updated on 3/28/2022
WSL automatic updates are on.

Kernel version: 5.10.102.1

I am not sure why wsl.exe --version is not working. I tried it in both cmd and powershell.
Repro Steps
Shift-click the Ubuntu-20.04 icon in a taskbar OR run Ubuntu-20.04 in the start menu.
Expected Behavior
This used to open another working terminal I could use.
Actual Behavior
I get the following message:
The Windows Subsystem for Linux instance has terminated second window.
Press any key to continue...

When I press a key it closes the window.
Diagnostic Logs
No response

This started happening to me last Friday (2024-02-02). It was working fine earlier in the day and I did not manually update anything. I have restarted my computer a few times with no luck. The original terminal I open keeps running without an issue. I often use multiple terminals at a time so this severely hampers my workflow.

Now when I close the original terminal (that works) and try to open Ubuntu again, I get this error.
When I run a wsl.exe --shutdown and then can open as many terminals that I want, but now I can longer open VSCode from my terminal.

The --version command being invalid and the --status command showing my WSL was pretty outdated (not updated since 2022 even though Automatic Updates were on) tipped me off that I probably needed to try an update manually.
I ran wsl.exe --update, installed the latest version, and now the --version command works. VSCode is still having problems connecting to the remote. I will continue to update this issue as I make progress, but I definitely needed to update my WSL version.

Resolved by:

Manually updating WSL wsl.exe --update
Deleting VSCode directory within Ubuntu: rm -rf ~/.vscode-server


text:
Add an option which only root user can execute Windows binary in WSL

Is your feature request related to a problem? Please describe.
I want that only root user is able to execute Windows binary in WSL.
Describe the solution you'd like
There is an option like rootOnly to enable this feature in wsl.conf. For example,
[interop]
rootOnly = true

And when WSL non-root user execute Windows binary will produce proper error message.
firejox@DESKTOP-2BCQGK7:~$ xxx.exe
xxx.exe permission denied

Describe alternatives you've considered
Currently, I can use chmod o= /run/WSL to forbid non-root user execute Windows binary. However, it produces ugly error message.
firejox@DESKTOP-2BCQGK7:~$ choice.exe
<3>WSL (841) ERROR: UtilConnectUnix:513: connect failed 13
                                                          firejox@DESKTOP-2BCQGK7:~$

/feature


text:
WSL installation fails with error "0x8007019e" plus "wsl -l -v" gives an error "Wsl/0x80080005"

Windows Version
10.0.22631.37372
WSL Version
2.2.4.0
Are you using WSL 1 or WSL 2?

[X] WSL 2
[ ] WSL 1

Kernel Version
5.15.153.1-2
Distro Version
Ubuntu 22.04
Other Software
No response
Repro Steps
wsl --install
wsl -l -v
Expected Behavior
wsl --install should install default distro as Ubuntu and lauch it
wsl -l -v should give WSL version
Actual Behavior
Executing wsl --install command returns an error "0x8007019e The Windows Subsystem for Linux has not been enabled.".
wsl --install
Ubuntu is already installed.
Launching Ubuntu...
Error: 0x8007019e The Windows Subsystem for Linux has not been enabled.
Press any key to continue...
The operation completed successfully.
Executing wsl -l -v command returns an error "Wsl/0x80080005".
wsl -l -v
Server execution failed
Error code: Wsl/0x80080005
Diagnostic Logs
No response

The first problem I ran into was an error "0x8007019e", which appeared when I tried to open Ubuntu after the installation (the first time installation didn't give any error). I tried to troubleshoot it following this issue https://github.com/microsoft/WSL/issues/10850. However, during troubleshooting I ran into error "Wsl/0x80080005". Then I tried to troubleshoot second error with this issue https://github.com/microsoft/WSL/issues/10305, but nothing helped. Developer mode is enabled, Hardware Virtualization is enabled and there is no "Windows Subsystem for Linux" in Windows components

Below are WSL logs (if I did them correctly, of course)
WslLogs-2024-08-08_13-30-30.zip

Thank you @Khajiit-Rakaj . Based on the error code, it looks like wslservice.exe is crashing. Can you follow 11) Reporting a WSL process crash
to capture a crash dump and share it with us ?

What a mess. Issues across the board with WSL2 right now on Windows 11 pro. After downgrading to 5.10 I was able to install Debian but not Ubuntu. One time Ubuntu got to the install with new username but froze up and never booted. Repeated attempts now throwing 0x80070040 consistently regardless.
gateway-logs-20240812-1306439300130772409261174.zip

authors: Khajiit-Rakaj OneBlue chris-piekarski


text:
wsl2: vpn on host machine

Hello,
Recently with wsl1 all network interfaces were replicated from windows machine.
With wsl2 because of hyper-v being used, the NAT interface is used and wsl2 doesn't see any vpn interfaces from host machine.
My question : Is there any way to replicate tunnel vpn interface in wsl2 ?
Also, so far wsl2 doesn't provide UI support for now, using vpn clients in wsl2 is not always possible because sometimes 2FA requires UI interaction with user.
version:

C:\Users\ddr>ver
Microsoft Windows [Version 10.0.18922.1000]

ipconfig on windows host, 10.10.177.21 is vpn address:

C:\Users\ddr>ipconfig
Windows IP Configuration
Ethernet adapter Local Area Connection* 2:
Connection-specific DNS Suffix  . :
Link-local IPv6 Address . . . . . : fe80::8424:b1a5:7586:8508%3
IPv4 Address. . . . . . . . . . . : 10.10.177.21
Subnet Mask . . . . . . . . . . . : 255.255.255.255
Default Gateway . . . . . . . . . : 0.0.0.0
Ethernet adapter Ethernet:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix  . :
Ethernet adapter Ethernet 2:
Connection-specific DNS Suffix  . :
Link-local IPv6 Address . . . . . : fe80::d470:2271:9f37:cf27%16
IPv4 Address. . . . . . . . . . . : 192.168.0.194
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.0.1

Thanks

My question : Is there any way to replicate tunnel vpn interface in wsl2 ?

Would have to be way more specific on "tunnel vpn" because the specifics on the answer to "is there any way" is going to be very sensitive to the nature of the VPN. Answer is almost always going to be "yes" (2FA or not), but you'll get way better answers if you ask in a forum with people familiar with the VPN in question.
That said, I get the feeling there is something else going on here, as yet unexplained. The quoth "I tried connect to a VPN in Windows a few time in them past, but every time I failed" over in #4201 has been nagging at me. It is certainly a true enough statement, but leaves unexplained the fail part. Your statement "the NAT interface is used and wsl2 doesn't see any vpn interfaces from host machine" in your OP leaves explanation as well. The fact WSL has it's own IP segment isn't notable (or special) in the context. Which is not on you; I don't know why your bytes aren't being routed into WSL2 either. My Windows VPN works fine (my provider happens to use OpenVPN +  TAP) but that doesn't help you because you aren't using my provider, areya).
Which is just to say, attacking this from the WSL2 side can almost certainly be made to work, with effort. But it probably isn't the right approach. If I had to guess (and I do), there is some (maybe simple) answer here for a certain class of VPNs that we're all missing. Otherwise every Hyper-V user would be screeching for the last decade.

@therealkenc , thanks for answering but unfortunately I didn't fully get it.
#4201 is about unsupported API and is not related to my question.
Let me briefly describe the  real question I'm faced now :

I use pulsesecure vpn client on Ubuntu VM to connect to VPN. It requires 2FA and requires UI support as asks for 2FA passphrase.
I can successfully connect to VPN both from windows host or from Ubuntu VM running in Hyper-V.
I can't connect to vpn from wsl2 because of UI being unsupported or via using host(windows) VPN/tunnel interface on wsl2 (or maybe I don't know the way how to configure that).

When wsl2 starts, it's eth0 is 172.x.x.x as it's behind the NAT. That's why I don't think any configuring of routing either on windows or wsl2 is applicable (as being answered in some issues here) to workaround my issue.
To say more, if you were watching wsl2 demo on ms-connect conference, the guys from MS were mentioning about replicating host network interfaces in wsl2. But looks like only default NAT is available for now.

and is not related to my question.

Yeah I get that a lot.
Hopefully someone from the community will  offer an answer more to your liking, and which you believe is more related to your question.

Just for your information, running GUI application on both WSL1 and WSL2 is possible. You need a Xserver on Windows host (either VcXsrv or cygwin/X will work), then export DISPLAY=<windows ip>:0. Detailed guides also available with some Googling.

@wangqr , thank you for comment. Yes, you are right and I was able to deal with NAT issue and tried wsl2 with xming.
I was able to start pulseUi from pulse vpn client. But unfortunately it emits an error while trying to connect to vpn :

ip6tables-restore: line 5 failed
I failed to find something reasonable about this error and it looks like this is an issue in pulse client.
That's why for now I postponed with this approach and switched back to virtual box.

I'm having this exact same issue. Converting back to WSL 1 is not really an option as that breaks other network functionality. Back to VMs I guess....

I solved this for my situation by establishing the VPN connection not from the windows host, but from within the WSL2 VM using openconnect. Obviously I cannot use the vpn connection on the Windows side, but that's ok for me. I'm also using X forwarding with XMing to be able to use a browser over de vpn connection

Similar problem here, started two-three weeks ago for me so something somewhere must have changed...
I've been running Ubuntu 20.04 in WSL2 since April, connecting to work using the Pulse Secure Win10 app and accessing the servers at work from both Windows and from within WSL2. I've had no problems with git fetch or git push until now, where fetching/pushing works for very small changes (10+ objects) but not for larger changes (~100+ objects) where push/fetch just hangs.
If i connect to work using the OpenConnect VPN client from inside WSL2 then it works fine. OpenConnect can be run in cli-only so it is an ok workaround for me.
I just have to convince the IT-department to allow more than one active VPN connection, right now I must choose between pushing from WSL2 or browsing the intranet from Windows 😄

The point is that my VPN server requires 2FA and only pulsesecure vpn UI client allows to connect.
Unfortunately OpenConnect cli doesn't work properly with 2FA.

@carlolars I'm unable to connect to my work VPN (Pulse secure) from WSL2 on Window 10 (1909). How did you manage that?

authors: ahazu carlolars dimarusyy ronaldwillems74 tanukus therealkenc wangqr