Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
}

Expand Down
143 changes: 143 additions & 0 deletions tests/baselines/reference/neverAsDiscriminantType(strict=false).js
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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))
}
}

Loading