mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 07:45:18 -06:00
Discriminant of type never should never be matched (#50755)
* Discriminant of type 'never' should never be matched * Add tests
This commit is contained in:
parent
e37ea53715
commit
60963d7216
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
66
tests/cases/compiler/neverAsDiscriminantType.ts
Normal file
66
tests/cases/compiler/neverAsDiscriminantType.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user