diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts new file mode 100644 index 00000000000..cea04f0818e --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts @@ -0,0 +1,43 @@ +// @declaration: true + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +function hasKind(entity: Entity, kind: "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is Entity; +function hasKind(entity: Entity, kind: Kind): boolean { + return kind === is; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts new file mode 100644 index 00000000000..b8ed1b47dd4 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts @@ -0,0 +1,21 @@ +// @declaration: true + +type T = "foo" | "bar" | "baz"; + +var x: "foo" | "bar" | "baz" = "foo"; +var y: T = "bar"; + +if (x === "foo") { + let a = x; +} +else if (x !== "bar") { + let b = x || y; +} +else { + let c = x; + let d = y; + let e: (typeof x) | (typeof y) = c || d; +} + +x = y; +y = x; \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes02.ts new file mode 100644 index 00000000000..2cc63ab4460 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes02.ts @@ -0,0 +1,21 @@ +// @declaration: true + +type T = string | "foo" | "bar" | "baz"; + +var x: "foo" | "bar" | "baz" | string = "foo"; +var y: T = "bar"; + +if (x === "foo") { + let a = x; +} +else if (x !== "bar") { + let b = x || y; +} +else { + let c = x; + let d = y; + let e: (typeof x) | (typeof y) = c || d; +} + +x = y; +y = x; \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts new file mode 100644 index 00000000000..d5c6a38af79 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts @@ -0,0 +1,21 @@ +// @declaration: true + +type T = number | "foo" | "bar"; + +var x: "foo" | "bar" | number; +var y: T = "bar"; + +if (x === "foo") { + let a = x; +} +else if (x !== "bar") { + let b = x || y; +} +else { + let c = x; + let d = y; + let e: (typeof x) | (typeof y) = c || d; +} + +x = y; +y = x; \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes04.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes04.ts new file mode 100644 index 00000000000..e9d062b0e5c --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes04.ts @@ -0,0 +1,38 @@ +// @declaration: true + +type T = "" | "foo"; + +let x: T = ""; +let y: T = "foo"; + +if (x === "") { + let a = x; +} + +if (x !== "") { + let b = x; +} + +if (x == "") { + let c = x; +} + +if (x != "") { + let d = x; +} + +if (x) { + let e = x; +} + +if (!x) { + let f = x; +} + +if (!!x) { + let g = x; +} + +if (!!!x) { + let h = x; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInVariableDeclarations01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInVariableDeclarations01.ts new file mode 100644 index 00000000000..4f006387687 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesInVariableDeclarations01.ts @@ -0,0 +1,19 @@ +// @declaration: true + +let a: ""; +var b: "foo"; +let c: "bar"; +const d: "baz"; + +a = ""; +b = "foo"; +c = "bar"; + +let e: "" = ""; +var f: "foo" = "foo"; +let g: "bar" = "bar"; +const h: "baz" = "baz"; + +e = ""; +f = "foo"; +g = "bar"; \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts new file mode 100644 index 00000000000..d88167eaeff --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts @@ -0,0 +1,53 @@ +// @declaration: true + +type PrimitiveName = 'string' | 'number' | 'boolean'; + +function getFalsyPrimitive(x: "string"): string; +function getFalsyPrimitive(x: "number"): number; +function getFalsyPrimitive(x: "boolean"): boolean; +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +function getFalsyPrimitive(x: "number" | "string"): number | string; +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +function getFalsyPrimitive(x: PrimitiveName) { + if (x === "string") { + return ""; + } + if (x === "number") { + return 0; + } + if (x === "boolean") { + return false; + } + + // Should be unreachable. + throw "Invalid value"; +} + +namespace Consts1 { + const EMPTY_STRING = getFalsyPrimitive("string"); + const ZERO = getFalsyPrimitive('number'); + const FALSE = getFalsyPrimitive("boolean"); +} + +const string: "string" = "string" +const number: "number" = "number" +const boolean: "boolean" = "boolean" + +const stringOrNumber = string || number; +const stringOrBoolean = string || boolean; +const booleanOrNumber = number || boolean; +const stringOrBooleanOrNumber = stringOrBoolean || number; + +namespace Consts2 { + const EMPTY_STRING = getFalsyPrimitive(string); + const ZERO = getFalsyPrimitive(number); + const FALSE = getFalsyPrimitive(boolean); + + const a = getFalsyPrimitive(stringOrNumber); + const b = getFalsyPrimitive(stringOrBoolean); + const c = getFalsyPrimitive(booleanOrNumber); + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +} + + diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads02.ts new file mode 100644 index 00000000000..5801aa50076 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads02.ts @@ -0,0 +1,51 @@ +// @declaration: true + +function getFalsyPrimitive(x: "string"): string; +function getFalsyPrimitive(x: "number"): number; +function getFalsyPrimitive(x: "boolean"): boolean; +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +function getFalsyPrimitive(x: "number" | "string"): number | string; +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +function getFalsyPrimitive(x: string) { + if (x === "string") { + return ""; + } + if (x === "number") { + return 0; + } + if (x === "boolean") { + return false; + } + + // Should be unreachable. + throw "Invalid value"; +} + +namespace Consts1 { + const EMPTY_STRING = getFalsyPrimitive("string"); + const ZERO = getFalsyPrimitive('number'); + const FALSE = getFalsyPrimitive("boolean"); +} + +const string: "string" = "string" +const number: "number" = "number" +const boolean: "boolean" = "boolean" + +const stringOrNumber = string || number; +const stringOrBoolean = string || boolean; +const booleanOrNumber = number || boolean; +const stringOrBooleanOrNumber = stringOrBoolean || number; + +namespace Consts2 { + const EMPTY_STRING = getFalsyPrimitive(string); + const ZERO = getFalsyPrimitive(number); + const FALSE = getFalsyPrimitive(boolean); + + const a = getFalsyPrimitive(stringOrNumber); + const b = getFalsyPrimitive(stringOrBoolean); + const c = getFalsyPrimitive(booleanOrNumber); + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +} + + diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesTypePredicates01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesTypePredicates01.ts new file mode 100644 index 00000000000..a78918c8122 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesTypePredicates01.ts @@ -0,0 +1,25 @@ +// @declaration: true + +type Kind = "A" | "B" + +function kindIs(kind: Kind, is: "A"): kind is "A"; +function kindIs(kind: Kind, is: "B"): kind is "B"; +function kindIs(kind: Kind, is: Kind): boolean { + return kind === is; +} + +var x: Kind = "A"; + +if (kindIs(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!kindIs(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file