Discriminant of type never should never be matched (#50755)

* Discriminant of type 'never' should never be matched

* Add tests
This commit is contained in:
Anders Hejlsberg 2022-09-13 10:29:50 -07:00 committed by GitHub
parent e37ea53715
commit 60963d7216
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1101 additions and 1 deletions

View File

@ -25130,7 +25130,7 @@ namespace ts {
const narrowedPropType = narrowType(propType);
return filterType(type, t => {
const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName);
return !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
});
}

View File

@ -0,0 +1,143 @@
//// [neverAsDiscriminantType.ts]
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
function f1(foo: Foo1) {
if (foo.kind === 'a') {
foo.a;
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
function f2(foo: Foo2) {
if (foo.kind === 'a') {
foo.a;
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
op: O
d: D
t?: T
s?: number
}
export type GatewayPayload = {
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
}[keyof GatewayEvents]
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
}[GatewayOpcode]
export interface GatewayParams {
[GatewayOpcode.HELLO]: { b: 1 }
}
export enum GatewayOpcode {
DISPATCH = 0,
HEARTBEAT = 1,
IDENTIFY = 2,
PRESENCE_UPDATE = 3,
VOICE_STATE_UPDATE = 4,
RESUME = 6,
RECONNECT = 7,
REQUEST_GUILD_MEMBERS = 8,
INVALID_SESSION = 9,
HELLO = 10,
HEARTBEAT_ACK = 11,
}
export interface GatewayEvents {
MESSAGE_CREATE: { a: 1 }
MESSAGE_UPDATE: { a: 2 }
MESSAGE_DELETE: { a: 3 }
}
function assertMessage(event: { a: 1 }) { }
export async function adaptSession(input: GatewayPayload) {
if (input.t === 'MESSAGE_CREATE') {
assertMessage(input.d)
}
}
//// [neverAsDiscriminantType.js]
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
exports.adaptSession = exports.GatewayOpcode = void 0;
function f1(foo) {
if (foo.kind === 'a') {
foo.a;
}
}
function f2(foo) {
if (foo.kind === 'a') {
foo.a;
}
}
var GatewayOpcode;
(function (GatewayOpcode) {
GatewayOpcode[GatewayOpcode["DISPATCH"] = 0] = "DISPATCH";
GatewayOpcode[GatewayOpcode["HEARTBEAT"] = 1] = "HEARTBEAT";
GatewayOpcode[GatewayOpcode["IDENTIFY"] = 2] = "IDENTIFY";
GatewayOpcode[GatewayOpcode["PRESENCE_UPDATE"] = 3] = "PRESENCE_UPDATE";
GatewayOpcode[GatewayOpcode["VOICE_STATE_UPDATE"] = 4] = "VOICE_STATE_UPDATE";
GatewayOpcode[GatewayOpcode["RESUME"] = 6] = "RESUME";
GatewayOpcode[GatewayOpcode["RECONNECT"] = 7] = "RECONNECT";
GatewayOpcode[GatewayOpcode["REQUEST_GUILD_MEMBERS"] = 8] = "REQUEST_GUILD_MEMBERS";
GatewayOpcode[GatewayOpcode["INVALID_SESSION"] = 9] = "INVALID_SESSION";
GatewayOpcode[GatewayOpcode["HELLO"] = 10] = "HELLO";
GatewayOpcode[GatewayOpcode["HEARTBEAT_ACK"] = 11] = "HEARTBEAT_ACK";
})(GatewayOpcode = exports.GatewayOpcode || (exports.GatewayOpcode = {}));
function assertMessage(event) { }
function adaptSession(input) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (input.t === 'MESSAGE_CREATE') {
assertMessage(input.d);
}
return [2 /*return*/];
});
});
}
exports.adaptSession = adaptSession;

View File

@ -0,0 +1,197 @@
=== tests/cases/compiler/neverAsDiscriminantType.ts ===
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
>Foo1 : Symbol(Foo1, Decl(neverAsDiscriminantType.ts, 0, 0))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 40))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 56))
function f1(foo: Foo1) {
>f1 : Symbol(f1, Decl(neverAsDiscriminantType.ts, 0, 71))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>Foo1 : Symbol(Foo1, Decl(neverAsDiscriminantType.ts, 0, 0))
if (foo.kind === 'a') {
>foo.kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13), Decl(neverAsDiscriminantType.ts, 0, 40), Decl(neverAsDiscriminantType.ts, 0, 56))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13), Decl(neverAsDiscriminantType.ts, 0, 40), Decl(neverAsDiscriminantType.ts, 0, 56))
foo.a;
>foo.a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
>Foo2 : Symbol(Foo2, Decl(neverAsDiscriminantType.ts, 6, 1))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 41))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 58))
function f2(foo: Foo2) {
>f2 : Symbol(f2, Decl(neverAsDiscriminantType.ts, 8, 74))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>Foo2 : Symbol(Foo2, Decl(neverAsDiscriminantType.ts, 6, 1))
if (foo.kind === 'a') {
>foo.kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13), Decl(neverAsDiscriminantType.ts, 8, 41), Decl(neverAsDiscriminantType.ts, 8, 58))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13), Decl(neverAsDiscriminantType.ts, 8, 41), Decl(neverAsDiscriminantType.ts, 8, 58))
foo.a;
>foo.a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 18, 41))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 18, 65))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>D : Symbol(D, Decl(neverAsDiscriminantType.ts, 18, 96))
op: O
>op : Symbol(GatewayPayloadStructure.op, Decl(neverAsDiscriminantType.ts, 18, 101))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 18, 41))
d: D
>d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
>D : Symbol(D, Decl(neverAsDiscriminantType.ts, 18, 96))
t?: T
>t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 18, 65))
s?: number
>s : Symbol(GatewayPayloadStructure.s, Decl(neverAsDiscriminantType.ts, 21, 9))
}
export type GatewayPayload = {
>GatewayPayload : Symbol(GatewayPayload, Decl(neverAsDiscriminantType.ts, 23, 1))
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
}[keyof GatewayEvents]
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
}[GatewayOpcode]
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
export interface GatewayParams {
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
[GatewayOpcode.HELLO]: { b: 1 }
>[GatewayOpcode.HELLO] : Symbol(GatewayParams[GatewayOpcode.HELLO], Decl(neverAsDiscriminantType.ts, 33, 32))
>GatewayOpcode.HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
>b : Symbol(b, Decl(neverAsDiscriminantType.ts, 34, 28))
}
export enum GatewayOpcode {
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
DISPATCH = 0,
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
HEARTBEAT = 1,
>HEARTBEAT : Symbol(GatewayOpcode.HEARTBEAT, Decl(neverAsDiscriminantType.ts, 38, 17))
IDENTIFY = 2,
>IDENTIFY : Symbol(GatewayOpcode.IDENTIFY, Decl(neverAsDiscriminantType.ts, 39, 18))
PRESENCE_UPDATE = 3,
>PRESENCE_UPDATE : Symbol(GatewayOpcode.PRESENCE_UPDATE, Decl(neverAsDiscriminantType.ts, 40, 17))
VOICE_STATE_UPDATE = 4,
>VOICE_STATE_UPDATE : Symbol(GatewayOpcode.VOICE_STATE_UPDATE, Decl(neverAsDiscriminantType.ts, 41, 24))
RESUME = 6,
>RESUME : Symbol(GatewayOpcode.RESUME, Decl(neverAsDiscriminantType.ts, 42, 27))
RECONNECT = 7,
>RECONNECT : Symbol(GatewayOpcode.RECONNECT, Decl(neverAsDiscriminantType.ts, 43, 15))
REQUEST_GUILD_MEMBERS = 8,
>REQUEST_GUILD_MEMBERS : Symbol(GatewayOpcode.REQUEST_GUILD_MEMBERS, Decl(neverAsDiscriminantType.ts, 44, 18))
INVALID_SESSION = 9,
>INVALID_SESSION : Symbol(GatewayOpcode.INVALID_SESSION, Decl(neverAsDiscriminantType.ts, 45, 30))
HELLO = 10,
>HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
HEARTBEAT_ACK = 11,
>HEARTBEAT_ACK : Symbol(GatewayOpcode.HEARTBEAT_ACK, Decl(neverAsDiscriminantType.ts, 47, 15))
}
export interface GatewayEvents {
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
MESSAGE_CREATE: { a: 1 }
>MESSAGE_CREATE : Symbol(GatewayEvents.MESSAGE_CREATE, Decl(neverAsDiscriminantType.ts, 51, 32))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 52, 21))
MESSAGE_UPDATE: { a: 2 }
>MESSAGE_UPDATE : Symbol(GatewayEvents.MESSAGE_UPDATE, Decl(neverAsDiscriminantType.ts, 52, 28))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 53, 21))
MESSAGE_DELETE: { a: 3 }
>MESSAGE_DELETE : Symbol(GatewayEvents.MESSAGE_DELETE, Decl(neverAsDiscriminantType.ts, 53, 28))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 54, 21))
}
function assertMessage(event: { a: 1 }) { }
>assertMessage : Symbol(assertMessage, Decl(neverAsDiscriminantType.ts, 55, 1))
>event : Symbol(event, Decl(neverAsDiscriminantType.ts, 57, 23))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 57, 31))
export async function adaptSession(input: GatewayPayload) {
>adaptSession : Symbol(adaptSession, Decl(neverAsDiscriminantType.ts, 57, 43))
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>GatewayPayload : Symbol(GatewayPayload, Decl(neverAsDiscriminantType.ts, 23, 1))
if (input.t === 'MESSAGE_CREATE') {
>input.t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8) ... and 8 more)
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8) ... and 8 more)
assertMessage(input.d)
>assertMessage : Symbol(assertMessage, Decl(neverAsDiscriminantType.ts, 55, 1))
>input.d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
}
}

View File

@ -0,0 +1,177 @@
=== tests/cases/compiler/neverAsDiscriminantType.ts ===
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
>Foo1 : { kind: 'a'; a: number; } | { kind: 'b'; } | { kind: never; }
>kind : "a"
>a : number
>kind : "b"
>kind : never
function f1(foo: Foo1) {
>f1 : (foo: Foo1) => void
>foo : Foo1
if (foo.kind === 'a') {
>foo.kind === 'a' : boolean
>foo.kind : "a" | "b"
>foo : Foo1
>kind : "a" | "b"
>'a' : "a"
foo.a;
>foo.a : number
>foo : { kind: "a"; a: number; }
>a : number
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
>Foo2 : { kind?: 'a'; a: number; } | { kind?: 'b'; } | { kind?: never; }
>kind : "a"
>a : number
>kind : "b"
>kind : never
function f2(foo: Foo2) {
>f2 : (foo: Foo2) => void
>foo : Foo2
if (foo.kind === 'a') {
>foo.kind === 'a' : boolean
>foo.kind : "a" | "b"
>foo : Foo2
>kind : "a" | "b"
>'a' : "a"
foo.a;
>foo.a : number
>foo : { kind?: "a"; a: number; }
>a : number
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
op: O
>op : O
d: D
>d : D
t?: T
>t : T
s?: number
>s : number
}
export type GatewayPayload = {
>GatewayPayload : GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_CREATE", { a: 1; }> | GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_UPDATE", { a: 2; }> | GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_DELETE", { a: 3; }> | GatewayPayloadStructure<GatewayOpcode.HEARTBEAT, never, never> | GatewayPayloadStructure<GatewayOpcode.IDENTIFY, never, never> | GatewayPayloadStructure<GatewayOpcode.PRESENCE_UPDATE, never, never> | GatewayPayloadStructure<GatewayOpcode.VOICE_STATE_UPDATE, never, never> | GatewayPayloadStructure<GatewayOpcode.RESUME, never, never> | GatewayPayloadStructure<GatewayOpcode.RECONNECT, never, never> | GatewayPayloadStructure<GatewayOpcode.REQUEST_GUILD_MEMBERS, never, never> | GatewayPayloadStructure<GatewayOpcode.INVALID_SESSION, never, never> | GatewayPayloadStructure<GatewayOpcode.HELLO, never, { b: 1; }> | GatewayPayloadStructure<GatewayOpcode.HEARTBEAT_ACK, never, never>
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
>GatewayOpcode : any
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
>GatewayOpcode : any
}[keyof GatewayEvents]
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
}[GatewayOpcode]
export interface GatewayParams {
[GatewayOpcode.HELLO]: { b: 1 }
>[GatewayOpcode.HELLO] : { b: 1; }
>GatewayOpcode.HELLO : GatewayOpcode.HELLO
>GatewayOpcode : typeof GatewayOpcode
>HELLO : GatewayOpcode.HELLO
>b : 1
}
export enum GatewayOpcode {
>GatewayOpcode : GatewayOpcode
DISPATCH = 0,
>DISPATCH : GatewayOpcode.DISPATCH
>0 : 0
HEARTBEAT = 1,
>HEARTBEAT : GatewayOpcode.HEARTBEAT
>1 : 1
IDENTIFY = 2,
>IDENTIFY : GatewayOpcode.IDENTIFY
>2 : 2
PRESENCE_UPDATE = 3,
>PRESENCE_UPDATE : GatewayOpcode.PRESENCE_UPDATE
>3 : 3
VOICE_STATE_UPDATE = 4,
>VOICE_STATE_UPDATE : GatewayOpcode.VOICE_STATE_UPDATE
>4 : 4
RESUME = 6,
>RESUME : GatewayOpcode.RESUME
>6 : 6
RECONNECT = 7,
>RECONNECT : GatewayOpcode.RECONNECT
>7 : 7
REQUEST_GUILD_MEMBERS = 8,
>REQUEST_GUILD_MEMBERS : GatewayOpcode.REQUEST_GUILD_MEMBERS
>8 : 8
INVALID_SESSION = 9,
>INVALID_SESSION : GatewayOpcode.INVALID_SESSION
>9 : 9
HELLO = 10,
>HELLO : GatewayOpcode.HELLO
>10 : 10
HEARTBEAT_ACK = 11,
>HEARTBEAT_ACK : GatewayOpcode.HEARTBEAT_ACK
>11 : 11
}
export interface GatewayEvents {
MESSAGE_CREATE: { a: 1 }
>MESSAGE_CREATE : { a: 1; }
>a : 1
MESSAGE_UPDATE: { a: 2 }
>MESSAGE_UPDATE : { a: 2; }
>a : 2
MESSAGE_DELETE: { a: 3 }
>MESSAGE_DELETE : { a: 3; }
>a : 3
}
function assertMessage(event: { a: 1 }) { }
>assertMessage : (event: { a: 1;}) => void
>event : { a: 1; }
>a : 1
export async function adaptSession(input: GatewayPayload) {
>adaptSession : (input: GatewayPayload) => Promise<void>
>input : GatewayPayload
if (input.t === 'MESSAGE_CREATE') {
>input.t === 'MESSAGE_CREATE' : boolean
>input.t : "MESSAGE_CREATE" | "MESSAGE_UPDATE" | "MESSAGE_DELETE"
>input : GatewayPayload
>t : "MESSAGE_CREATE" | "MESSAGE_UPDATE" | "MESSAGE_DELETE"
>'MESSAGE_CREATE' : "MESSAGE_CREATE"
assertMessage(input.d)
>assertMessage(input.d) : void
>assertMessage : (event: { a: 1; }) => void
>input.d : { a: 1; }
>input : GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_CREATE", { a: 1; }>
>d : { a: 1; }
}
}

View File

@ -0,0 +1,143 @@
//// [neverAsDiscriminantType.ts]
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
function f1(foo: Foo1) {
if (foo.kind === 'a') {
foo.a;
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
function f2(foo: Foo2) {
if (foo.kind === 'a') {
foo.a;
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
op: O
d: D
t?: T
s?: number
}
export type GatewayPayload = {
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
}[keyof GatewayEvents]
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
}[GatewayOpcode]
export interface GatewayParams {
[GatewayOpcode.HELLO]: { b: 1 }
}
export enum GatewayOpcode {
DISPATCH = 0,
HEARTBEAT = 1,
IDENTIFY = 2,
PRESENCE_UPDATE = 3,
VOICE_STATE_UPDATE = 4,
RESUME = 6,
RECONNECT = 7,
REQUEST_GUILD_MEMBERS = 8,
INVALID_SESSION = 9,
HELLO = 10,
HEARTBEAT_ACK = 11,
}
export interface GatewayEvents {
MESSAGE_CREATE: { a: 1 }
MESSAGE_UPDATE: { a: 2 }
MESSAGE_DELETE: { a: 3 }
}
function assertMessage(event: { a: 1 }) { }
export async function adaptSession(input: GatewayPayload) {
if (input.t === 'MESSAGE_CREATE') {
assertMessage(input.d)
}
}
//// [neverAsDiscriminantType.js]
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
exports.adaptSession = exports.GatewayOpcode = void 0;
function f1(foo) {
if (foo.kind === 'a') {
foo.a;
}
}
function f2(foo) {
if (foo.kind === 'a') {
foo.a;
}
}
var GatewayOpcode;
(function (GatewayOpcode) {
GatewayOpcode[GatewayOpcode["DISPATCH"] = 0] = "DISPATCH";
GatewayOpcode[GatewayOpcode["HEARTBEAT"] = 1] = "HEARTBEAT";
GatewayOpcode[GatewayOpcode["IDENTIFY"] = 2] = "IDENTIFY";
GatewayOpcode[GatewayOpcode["PRESENCE_UPDATE"] = 3] = "PRESENCE_UPDATE";
GatewayOpcode[GatewayOpcode["VOICE_STATE_UPDATE"] = 4] = "VOICE_STATE_UPDATE";
GatewayOpcode[GatewayOpcode["RESUME"] = 6] = "RESUME";
GatewayOpcode[GatewayOpcode["RECONNECT"] = 7] = "RECONNECT";
GatewayOpcode[GatewayOpcode["REQUEST_GUILD_MEMBERS"] = 8] = "REQUEST_GUILD_MEMBERS";
GatewayOpcode[GatewayOpcode["INVALID_SESSION"] = 9] = "INVALID_SESSION";
GatewayOpcode[GatewayOpcode["HELLO"] = 10] = "HELLO";
GatewayOpcode[GatewayOpcode["HEARTBEAT_ACK"] = 11] = "HEARTBEAT_ACK";
})(GatewayOpcode = exports.GatewayOpcode || (exports.GatewayOpcode = {}));
function assertMessage(event) { }
function adaptSession(input) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (input.t === 'MESSAGE_CREATE') {
assertMessage(input.d);
}
return [2 /*return*/];
});
});
}
exports.adaptSession = adaptSession;

View File

@ -0,0 +1,197 @@
=== tests/cases/compiler/neverAsDiscriminantType.ts ===
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
>Foo1 : Symbol(Foo1, Decl(neverAsDiscriminantType.ts, 0, 0))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 40))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 56))
function f1(foo: Foo1) {
>f1 : Symbol(f1, Decl(neverAsDiscriminantType.ts, 0, 71))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>Foo1 : Symbol(Foo1, Decl(neverAsDiscriminantType.ts, 0, 0))
if (foo.kind === 'a') {
>foo.kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13), Decl(neverAsDiscriminantType.ts, 0, 40), Decl(neverAsDiscriminantType.ts, 0, 56))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 0, 13), Decl(neverAsDiscriminantType.ts, 0, 40), Decl(neverAsDiscriminantType.ts, 0, 56))
foo.a;
>foo.a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 2, 12))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 0, 24))
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
>Foo2 : Symbol(Foo2, Decl(neverAsDiscriminantType.ts, 6, 1))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 41))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 58))
function f2(foo: Foo2) {
>f2 : Symbol(f2, Decl(neverAsDiscriminantType.ts, 8, 74))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>Foo2 : Symbol(Foo2, Decl(neverAsDiscriminantType.ts, 6, 1))
if (foo.kind === 'a') {
>foo.kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13), Decl(neverAsDiscriminantType.ts, 8, 41), Decl(neverAsDiscriminantType.ts, 8, 58))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>kind : Symbol(kind, Decl(neverAsDiscriminantType.ts, 8, 13), Decl(neverAsDiscriminantType.ts, 8, 41), Decl(neverAsDiscriminantType.ts, 8, 58))
foo.a;
>foo.a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
>foo : Symbol(foo, Decl(neverAsDiscriminantType.ts, 10, 12))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 8, 25))
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 18, 41))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 18, 65))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>D : Symbol(D, Decl(neverAsDiscriminantType.ts, 18, 96))
op: O
>op : Symbol(GatewayPayloadStructure.op, Decl(neverAsDiscriminantType.ts, 18, 101))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 18, 41))
d: D
>d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
>D : Symbol(D, Decl(neverAsDiscriminantType.ts, 18, 96))
t?: T
>t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 18, 65))
s?: number
>s : Symbol(GatewayPayloadStructure.s, Decl(neverAsDiscriminantType.ts, 21, 9))
}
export type GatewayPayload = {
>GatewayPayload : Symbol(GatewayPayload, Decl(neverAsDiscriminantType.ts, 23, 1))
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
>T : Symbol(T, Decl(neverAsDiscriminantType.ts, 28, 9))
}[keyof GatewayEvents]
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
>GatewayPayloadStructure : Symbol(GatewayPayloadStructure, Decl(neverAsDiscriminantType.ts, 14, 1))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
>O : Symbol(O, Decl(neverAsDiscriminantType.ts, 26, 5))
}[GatewayOpcode]
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
export interface GatewayParams {
>GatewayParams : Symbol(GatewayParams, Decl(neverAsDiscriminantType.ts, 31, 16))
[GatewayOpcode.HELLO]: { b: 1 }
>[GatewayOpcode.HELLO] : Symbol(GatewayParams[GatewayOpcode.HELLO], Decl(neverAsDiscriminantType.ts, 33, 32))
>GatewayOpcode.HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
>HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
>b : Symbol(b, Decl(neverAsDiscriminantType.ts, 34, 28))
}
export enum GatewayOpcode {
>GatewayOpcode : Symbol(GatewayOpcode, Decl(neverAsDiscriminantType.ts, 35, 1))
DISPATCH = 0,
>DISPATCH : Symbol(GatewayOpcode.DISPATCH, Decl(neverAsDiscriminantType.ts, 37, 27))
HEARTBEAT = 1,
>HEARTBEAT : Symbol(GatewayOpcode.HEARTBEAT, Decl(neverAsDiscriminantType.ts, 38, 17))
IDENTIFY = 2,
>IDENTIFY : Symbol(GatewayOpcode.IDENTIFY, Decl(neverAsDiscriminantType.ts, 39, 18))
PRESENCE_UPDATE = 3,
>PRESENCE_UPDATE : Symbol(GatewayOpcode.PRESENCE_UPDATE, Decl(neverAsDiscriminantType.ts, 40, 17))
VOICE_STATE_UPDATE = 4,
>VOICE_STATE_UPDATE : Symbol(GatewayOpcode.VOICE_STATE_UPDATE, Decl(neverAsDiscriminantType.ts, 41, 24))
RESUME = 6,
>RESUME : Symbol(GatewayOpcode.RESUME, Decl(neverAsDiscriminantType.ts, 42, 27))
RECONNECT = 7,
>RECONNECT : Symbol(GatewayOpcode.RECONNECT, Decl(neverAsDiscriminantType.ts, 43, 15))
REQUEST_GUILD_MEMBERS = 8,
>REQUEST_GUILD_MEMBERS : Symbol(GatewayOpcode.REQUEST_GUILD_MEMBERS, Decl(neverAsDiscriminantType.ts, 44, 18))
INVALID_SESSION = 9,
>INVALID_SESSION : Symbol(GatewayOpcode.INVALID_SESSION, Decl(neverAsDiscriminantType.ts, 45, 30))
HELLO = 10,
>HELLO : Symbol(GatewayOpcode.HELLO, Decl(neverAsDiscriminantType.ts, 46, 24))
HEARTBEAT_ACK = 11,
>HEARTBEAT_ACK : Symbol(GatewayOpcode.HEARTBEAT_ACK, Decl(neverAsDiscriminantType.ts, 47, 15))
}
export interface GatewayEvents {
>GatewayEvents : Symbol(GatewayEvents, Decl(neverAsDiscriminantType.ts, 49, 1))
MESSAGE_CREATE: { a: 1 }
>MESSAGE_CREATE : Symbol(GatewayEvents.MESSAGE_CREATE, Decl(neverAsDiscriminantType.ts, 51, 32))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 52, 21))
MESSAGE_UPDATE: { a: 2 }
>MESSAGE_UPDATE : Symbol(GatewayEvents.MESSAGE_UPDATE, Decl(neverAsDiscriminantType.ts, 52, 28))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 53, 21))
MESSAGE_DELETE: { a: 3 }
>MESSAGE_DELETE : Symbol(GatewayEvents.MESSAGE_DELETE, Decl(neverAsDiscriminantType.ts, 53, 28))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 54, 21))
}
function assertMessage(event: { a: 1 }) { }
>assertMessage : Symbol(assertMessage, Decl(neverAsDiscriminantType.ts, 55, 1))
>event : Symbol(event, Decl(neverAsDiscriminantType.ts, 57, 23))
>a : Symbol(a, Decl(neverAsDiscriminantType.ts, 57, 31))
export async function adaptSession(input: GatewayPayload) {
>adaptSession : Symbol(adaptSession, Decl(neverAsDiscriminantType.ts, 57, 43))
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>GatewayPayload : Symbol(GatewayPayload, Decl(neverAsDiscriminantType.ts, 23, 1))
if (input.t === 'MESSAGE_CREATE') {
>input.t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8) ... and 8 more)
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>t : Symbol(GatewayPayloadStructure.t, Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8), Decl(neverAsDiscriminantType.ts, 20, 8) ... and 8 more)
assertMessage(input.d)
>assertMessage : Symbol(assertMessage, Decl(neverAsDiscriminantType.ts, 55, 1))
>input.d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
>input : Symbol(input, Decl(neverAsDiscriminantType.ts, 59, 35))
>d : Symbol(GatewayPayloadStructure.d, Decl(neverAsDiscriminantType.ts, 19, 9))
}
}

View File

@ -0,0 +1,177 @@
=== tests/cases/compiler/neverAsDiscriminantType.ts ===
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
>Foo1 : { kind: 'a'; a: number; } | { kind: 'b'; } | { kind: never; }
>kind : "a"
>a : number
>kind : "b"
>kind : never
function f1(foo: Foo1) {
>f1 : (foo: Foo1) => void
>foo : Foo1
if (foo.kind === 'a') {
>foo.kind === 'a' : boolean
>foo.kind : "a" | "b"
>foo : Foo1
>kind : "a" | "b"
>'a' : "a"
foo.a;
>foo.a : number
>foo : { kind: "a"; a: number; }
>a : number
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
>Foo2 : { kind?: "a" | undefined; a: number; } | { kind?: "b" | undefined; } | { kind?: undefined; }
>kind : "a" | undefined
>a : number
>kind : "b" | undefined
>kind : undefined
function f2(foo: Foo2) {
>f2 : (foo: Foo2) => void
>foo : Foo2
if (foo.kind === 'a') {
>foo.kind === 'a' : boolean
>foo.kind : "a" | "b" | undefined
>foo : Foo2
>kind : "a" | "b" | undefined
>'a' : "a"
foo.a;
>foo.a : number
>foo : { kind?: "a" | undefined; a: number; }
>a : number
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
op: O
>op : O
d: D
>d : D
t?: T
>t : T | undefined
s?: number
>s : number | undefined
}
export type GatewayPayload = {
>GatewayPayload : GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_CREATE", { a: 1; }> | GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_UPDATE", { a: 2; }> | GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_DELETE", { a: 3; }> | GatewayPayloadStructure<GatewayOpcode.HEARTBEAT, never, never> | GatewayPayloadStructure<GatewayOpcode.IDENTIFY, never, never> | GatewayPayloadStructure<GatewayOpcode.PRESENCE_UPDATE, never, never> | GatewayPayloadStructure<GatewayOpcode.VOICE_STATE_UPDATE, never, never> | GatewayPayloadStructure<GatewayOpcode.RESUME, never, never> | GatewayPayloadStructure<GatewayOpcode.RECONNECT, never, never> | GatewayPayloadStructure<GatewayOpcode.REQUEST_GUILD_MEMBERS, never, never> | GatewayPayloadStructure<GatewayOpcode.INVALID_SESSION, never, never> | GatewayPayloadStructure<GatewayOpcode.HELLO, never, { b: 1; }> | GatewayPayloadStructure<GatewayOpcode.HEARTBEAT_ACK, never, never>
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
>GatewayOpcode : any
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
>GatewayOpcode : any
}[keyof GatewayEvents]
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
}[GatewayOpcode]
export interface GatewayParams {
[GatewayOpcode.HELLO]: { b: 1 }
>[GatewayOpcode.HELLO] : { b: 1; }
>GatewayOpcode.HELLO : GatewayOpcode.HELLO
>GatewayOpcode : typeof GatewayOpcode
>HELLO : GatewayOpcode.HELLO
>b : 1
}
export enum GatewayOpcode {
>GatewayOpcode : GatewayOpcode
DISPATCH = 0,
>DISPATCH : GatewayOpcode.DISPATCH
>0 : 0
HEARTBEAT = 1,
>HEARTBEAT : GatewayOpcode.HEARTBEAT
>1 : 1
IDENTIFY = 2,
>IDENTIFY : GatewayOpcode.IDENTIFY
>2 : 2
PRESENCE_UPDATE = 3,
>PRESENCE_UPDATE : GatewayOpcode.PRESENCE_UPDATE
>3 : 3
VOICE_STATE_UPDATE = 4,
>VOICE_STATE_UPDATE : GatewayOpcode.VOICE_STATE_UPDATE
>4 : 4
RESUME = 6,
>RESUME : GatewayOpcode.RESUME
>6 : 6
RECONNECT = 7,
>RECONNECT : GatewayOpcode.RECONNECT
>7 : 7
REQUEST_GUILD_MEMBERS = 8,
>REQUEST_GUILD_MEMBERS : GatewayOpcode.REQUEST_GUILD_MEMBERS
>8 : 8
INVALID_SESSION = 9,
>INVALID_SESSION : GatewayOpcode.INVALID_SESSION
>9 : 9
HELLO = 10,
>HELLO : GatewayOpcode.HELLO
>10 : 10
HEARTBEAT_ACK = 11,
>HEARTBEAT_ACK : GatewayOpcode.HEARTBEAT_ACK
>11 : 11
}
export interface GatewayEvents {
MESSAGE_CREATE: { a: 1 }
>MESSAGE_CREATE : { a: 1; }
>a : 1
MESSAGE_UPDATE: { a: 2 }
>MESSAGE_UPDATE : { a: 2; }
>a : 2
MESSAGE_DELETE: { a: 3 }
>MESSAGE_DELETE : { a: 3; }
>a : 3
}
function assertMessage(event: { a: 1 }) { }
>assertMessage : (event: { a: 1;}) => void
>event : { a: 1; }
>a : 1
export async function adaptSession(input: GatewayPayload) {
>adaptSession : (input: GatewayPayload) => Promise<void>
>input : GatewayPayload
if (input.t === 'MESSAGE_CREATE') {
>input.t === 'MESSAGE_CREATE' : boolean
>input.t : "MESSAGE_CREATE" | "MESSAGE_UPDATE" | "MESSAGE_DELETE" | undefined
>input : GatewayPayload
>t : "MESSAGE_CREATE" | "MESSAGE_UPDATE" | "MESSAGE_DELETE" | undefined
>'MESSAGE_CREATE' : "MESSAGE_CREATE"
assertMessage(input.d)
>assertMessage(input.d) : void
>assertMessage : (event: { a: 1; }) => void
>input.d : { a: 1; }
>input : GatewayPayloadStructure<GatewayOpcode.DISPATCH, "MESSAGE_CREATE", { a: 1; }>
>d : { a: 1; }
}
}

View File

@ -0,0 +1,66 @@
// @strict: true, false
type Foo1 = { kind: 'a', a: number } | { kind: 'b' } | { kind: never };
function f1(foo: Foo1) {
if (foo.kind === 'a') {
foo.a;
}
}
type Foo2 = { kind?: 'a', a: number } | { kind?: 'b' } | { kind?: never };
function f2(foo: Foo2) {
if (foo.kind === 'a') {
foo.a;
}
}
// Repro from #50716
export interface GatewayPayloadStructure<O extends GatewayOpcode, T extends keyof GatewayEvents, D> {
op: O
d: D
t?: T
s?: number
}
export type GatewayPayload = {
[O in GatewayOpcode]: O extends GatewayOpcode.DISPATCH
? {
[T in keyof GatewayEvents]: GatewayPayloadStructure<GatewayOpcode.DISPATCH, T, GatewayEvents[T]>
}[keyof GatewayEvents]
: GatewayPayloadStructure<O, never, O extends keyof GatewayParams ? GatewayParams[O] : never>
}[GatewayOpcode]
export interface GatewayParams {
[GatewayOpcode.HELLO]: { b: 1 }
}
export enum GatewayOpcode {
DISPATCH = 0,
HEARTBEAT = 1,
IDENTIFY = 2,
PRESENCE_UPDATE = 3,
VOICE_STATE_UPDATE = 4,
RESUME = 6,
RECONNECT = 7,
REQUEST_GUILD_MEMBERS = 8,
INVALID_SESSION = 9,
HELLO = 10,
HEARTBEAT_ACK = 11,
}
export interface GatewayEvents {
MESSAGE_CREATE: { a: 1 }
MESSAGE_UPDATE: { a: 2 }
MESSAGE_DELETE: { a: 3 }
}
function assertMessage(event: { a: 1 }) { }
export async function adaptSession(input: GatewayPayload) {
if (input.t === 'MESSAGE_CREATE') {
assertMessage(input.d)
}
}