mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Allow nongeneric string mapping types to exist (#47050)
* Allow nongeneric string mapping types to exist * Accept baseline * Recusive membership testing function * Fix lint * Add @DanielRosenwasser's comment
This commit is contained in:
parent
86d5040031
commit
5c4caafc2a
@ -12182,7 +12182,7 @@ namespace ts {
|
||||
}
|
||||
if (t.flags & TypeFlags.StringMapping) {
|
||||
const constraint = getBaseConstraint((t as StringMappingType).type);
|
||||
return constraint ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType;
|
||||
return constraint && constraint !== (t as StringMappingType).type ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType;
|
||||
}
|
||||
if (t.flags & TypeFlags.IndexedAccess) {
|
||||
if (isMappedTypeGenericIndexedAccess(t)) {
|
||||
@ -15381,8 +15381,11 @@ namespace ts {
|
||||
|
||||
function getStringMappingType(symbol: Symbol, type: Type): Type {
|
||||
return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) :
|
||||
isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) :
|
||||
// Mapping<Mapping<T>> === Mapping<T>
|
||||
type.flags & TypeFlags.StringMapping && symbol === type.symbol ? type :
|
||||
isGenericIndexType(type) || isPatternLiteralPlaceholderType(type) ? getStringMappingTypeForGenericType(symbol, isPatternLiteralPlaceholderType(type) && !(type.flags & TypeFlags.StringMapping) ? getTemplateLiteralType(["", ""], [type]) : type) :
|
||||
type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) :
|
||||
type.flags & TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as TemplateLiteralType).texts, (type as TemplateLiteralType).types)) :
|
||||
type;
|
||||
}
|
||||
|
||||
@ -15396,6 +15399,16 @@ namespace ts {
|
||||
return str;
|
||||
}
|
||||
|
||||
function applyTemplateStringMapping(symbol: Symbol, texts: readonly string[], types: readonly Type[]): [texts: readonly string[], types: readonly Type[]] {
|
||||
switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {
|
||||
case IntrinsicTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))];
|
||||
case IntrinsicTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))];
|
||||
case IntrinsicTypeKind.Capitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types];
|
||||
case IntrinsicTypeKind.Uncapitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types];
|
||||
}
|
||||
return [texts, types];
|
||||
}
|
||||
|
||||
function getStringMappingTypeForGenericType(symbol: Symbol, type: Type): Type {
|
||||
const id = `${getSymbolId(symbol)},${getTypeId(type)}`;
|
||||
let result = stringMappingTypes.get(id);
|
||||
@ -15651,8 +15664,8 @@ namespace ts {
|
||||
accessNode;
|
||||
}
|
||||
|
||||
function isPatternLiteralPlaceholderType(type: Type) {
|
||||
return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt));
|
||||
function isPatternLiteralPlaceholderType(type: Type): boolean {
|
||||
return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || !!(type.flags & TypeFlags.StringMapping && isPatternLiteralPlaceholderType((type as StringMappingType).type));
|
||||
}
|
||||
|
||||
function isPatternLiteralType(type: Type) {
|
||||
@ -19613,6 +19626,13 @@ namespace ts {
|
||||
return Ternary.True;
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.StringMapping) {
|
||||
if (!(source.flags & TypeFlags.StringMapping)) {
|
||||
if (isMemberOfStringMapping(source, target)) {
|
||||
return Ternary.True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceFlags & TypeFlags.TypeVariable) {
|
||||
// IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch
|
||||
@ -19657,7 +19677,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (sourceFlags & TypeFlags.StringMapping) {
|
||||
if (targetFlags & TypeFlags.StringMapping && (source as StringMappingType).symbol === (target as StringMappingType).symbol) {
|
||||
if (targetFlags & TypeFlags.StringMapping) {
|
||||
if ((source as StringMappingType).symbol !== (target as StringMappingType).symbol) {
|
||||
return Ternary.False;
|
||||
}
|
||||
if (result = isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, reportErrors)) {
|
||||
resetErrorInfo(saveErrorInfo);
|
||||
return result;
|
||||
@ -20611,7 +20634,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral);
|
||||
return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral) || !!(type.flags & TypeFlags.StringMapping);
|
||||
}
|
||||
|
||||
function getExactOptionalUnassignableProperties(source: Type, target: Type) {
|
||||
@ -22171,6 +22194,32 @@ namespace ts {
|
||||
&& (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) }));
|
||||
}
|
||||
|
||||
function isMemberOfStringMapping(source: Type, target: Type): boolean {
|
||||
if (target.flags & (TypeFlags.String | TypeFlags.AnyOrUnknown)) {
|
||||
return true;
|
||||
}
|
||||
if (target.flags & TypeFlags.TemplateLiteral) {
|
||||
return isTypeAssignableTo(source, target);
|
||||
}
|
||||
if (target.flags & TypeFlags.StringMapping) {
|
||||
// We need to see whether applying the same mappings of the target
|
||||
// onto the source would produce an identical type *and* that
|
||||
// it's compatible with the inner-most non-string-mapped type.
|
||||
//
|
||||
// The intuition here is that if same mappings don't affect the source at all,
|
||||
// and the source is compatible with the unmapped target, then they must
|
||||
// still reside in the same domain.
|
||||
const mappingStack = [];
|
||||
while (target.flags & TypeFlags.StringMapping) {
|
||||
mappingStack.unshift(target.symbol);
|
||||
target = (target as StringMappingType).type;
|
||||
}
|
||||
const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source);
|
||||
return mappedSource === source && isMemberOfStringMapping(source, target);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean {
|
||||
if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) {
|
||||
return true;
|
||||
@ -22179,7 +22228,8 @@ namespace ts {
|
||||
const value = (source as StringLiteralType).value;
|
||||
return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
|
||||
target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) ||
|
||||
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName);
|
||||
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName ||
|
||||
target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target));
|
||||
}
|
||||
if (source.flags & TypeFlags.TemplateLiteral) {
|
||||
const texts = (source as TemplateLiteralType).texts;
|
||||
|
||||
@ -13,8 +13,8 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
|
||||
==== tests/cases/conformance/types/typeAliases/intrinsicTypes.ts (8 errors) ====
|
||||
type TU1 = Uppercase<'hello'>; // "HELLO"
|
||||
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
|
||||
type TU3 = Uppercase<string>; // string
|
||||
type TU4 = Uppercase<any>; // any
|
||||
type TU3 = Uppercase<string>; // Uppercase<string>
|
||||
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
|
||||
type TU5 = Uppercase<never>; // never
|
||||
type TU6 = Uppercase<42>; // Error
|
||||
~~
|
||||
@ -22,8 +22,8 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
|
||||
|
||||
type TL1 = Lowercase<'HELLO'>; // "hello"
|
||||
type TL2 = Lowercase<'FOO' | 'BAR'>; // "foo" | "bar"
|
||||
type TL3 = Lowercase<string>; // string
|
||||
type TL4 = Lowercase<any>; // any
|
||||
type TL3 = Lowercase<string>; // Lowercase<string>
|
||||
type TL4 = Lowercase<any>; // Lowercase<`${any}`>
|
||||
type TL5 = Lowercase<never>; // never
|
||||
type TL6 = Lowercase<42>; // Error
|
||||
~~
|
||||
@ -31,8 +31,8 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
|
||||
|
||||
type TC1 = Capitalize<'hello'>; // "Hello"
|
||||
type TC2 = Capitalize<'foo' | 'bar'>; // "Foo" | "Bar"
|
||||
type TC3 = Capitalize<string>; // string
|
||||
type TC4 = Capitalize<any>; // any
|
||||
type TC3 = Capitalize<string>; // Capitalize<string>
|
||||
type TC4 = Capitalize<any>; // Capitalize<`${any}`>
|
||||
type TC5 = Capitalize<never>; // never
|
||||
type TC6 = Capitalize<42>; // Error
|
||||
~~
|
||||
@ -40,8 +40,8 @@ tests/cases/conformance/types/typeAliases/intrinsicTypes.ts(43,5): error TS2322:
|
||||
|
||||
type TN1 = Uncapitalize<'Hello'>; // "hello"
|
||||
type TN2 = Uncapitalize<'Foo' | 'Bar'>; // "foo" | "bar"
|
||||
type TN3 = Uncapitalize<string>; // string
|
||||
type TN4 = Uncapitalize<any>; // any
|
||||
type TN3 = Uncapitalize<string>; // Uncapitalize<string>
|
||||
type TN4 = Uncapitalize<any>; // Uncapitalize<`${any}`>
|
||||
type TN5 = Uncapitalize<never>; // never
|
||||
type TN6 = Uncapitalize<42>; // Error
|
||||
~~
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
//// [intrinsicTypes.ts]
|
||||
type TU1 = Uppercase<'hello'>; // "HELLO"
|
||||
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
|
||||
type TU3 = Uppercase<string>; // string
|
||||
type TU4 = Uppercase<any>; // any
|
||||
type TU3 = Uppercase<string>; // Uppercase<string>
|
||||
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
|
||||
type TU5 = Uppercase<never>; // never
|
||||
type TU6 = Uppercase<42>; // Error
|
||||
|
||||
type TL1 = Lowercase<'HELLO'>; // "hello"
|
||||
type TL2 = Lowercase<'FOO' | 'BAR'>; // "foo" | "bar"
|
||||
type TL3 = Lowercase<string>; // string
|
||||
type TL4 = Lowercase<any>; // any
|
||||
type TL3 = Lowercase<string>; // Lowercase<string>
|
||||
type TL4 = Lowercase<any>; // Lowercase<`${any}`>
|
||||
type TL5 = Lowercase<never>; // never
|
||||
type TL6 = Lowercase<42>; // Error
|
||||
|
||||
type TC1 = Capitalize<'hello'>; // "Hello"
|
||||
type TC2 = Capitalize<'foo' | 'bar'>; // "Foo" | "Bar"
|
||||
type TC3 = Capitalize<string>; // string
|
||||
type TC4 = Capitalize<any>; // any
|
||||
type TC3 = Capitalize<string>; // Capitalize<string>
|
||||
type TC4 = Capitalize<any>; // Capitalize<`${any}`>
|
||||
type TC5 = Capitalize<never>; // never
|
||||
type TC6 = Capitalize<42>; // Error
|
||||
|
||||
type TN1 = Uncapitalize<'Hello'>; // "hello"
|
||||
type TN2 = Uncapitalize<'Foo' | 'Bar'>; // "foo" | "bar"
|
||||
type TN3 = Uncapitalize<string>; // string
|
||||
type TN4 = Uncapitalize<any>; // any
|
||||
type TN3 = Uncapitalize<string>; // Uncapitalize<string>
|
||||
type TN4 = Uncapitalize<any>; // Uncapitalize<`${any}`>
|
||||
type TN5 = Uncapitalize<never>; // never
|
||||
type TN6 = Uncapitalize<42>; // Error
|
||||
|
||||
|
||||
@ -7,11 +7,11 @@ type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
|
||||
>TU2 : Symbol(TU2, Decl(intrinsicTypes.ts, 0, 30))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TU3 = Uppercase<string>; // string
|
||||
type TU3 = Uppercase<string>; // Uppercase<string>
|
||||
>TU3 : Symbol(TU3, Decl(intrinsicTypes.ts, 1, 36))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TU4 = Uppercase<any>; // any
|
||||
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
|
||||
>TU4 : Symbol(TU4, Decl(intrinsicTypes.ts, 2, 29))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
@ -31,11 +31,11 @@ type TL2 = Lowercase<'FOO' | 'BAR'>; // "foo" | "bar"
|
||||
>TL2 : Symbol(TL2, Decl(intrinsicTypes.ts, 7, 30))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TL3 = Lowercase<string>; // string
|
||||
type TL3 = Lowercase<string>; // Lowercase<string>
|
||||
>TL3 : Symbol(TL3, Decl(intrinsicTypes.ts, 8, 36))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TL4 = Lowercase<any>; // any
|
||||
type TL4 = Lowercase<any>; // Lowercase<`${any}`>
|
||||
>TL4 : Symbol(TL4, Decl(intrinsicTypes.ts, 9, 29))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
@ -55,11 +55,11 @@ type TC2 = Capitalize<'foo' | 'bar'>; // "Foo" | "Bar"
|
||||
>TC2 : Symbol(TC2, Decl(intrinsicTypes.ts, 14, 31))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TC3 = Capitalize<string>; // string
|
||||
type TC3 = Capitalize<string>; // Capitalize<string>
|
||||
>TC3 : Symbol(TC3, Decl(intrinsicTypes.ts, 15, 37))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TC4 = Capitalize<any>; // any
|
||||
type TC4 = Capitalize<any>; // Capitalize<`${any}`>
|
||||
>TC4 : Symbol(TC4, Decl(intrinsicTypes.ts, 16, 30))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
@ -79,11 +79,11 @@ type TN2 = Uncapitalize<'Foo' | 'Bar'>; // "foo" | "bar"
|
||||
>TN2 : Symbol(TN2, Decl(intrinsicTypes.ts, 21, 33))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TN3 = Uncapitalize<string>; // string
|
||||
type TN3 = Uncapitalize<string>; // Uncapitalize<string>
|
||||
>TN3 : Symbol(TN3, Decl(intrinsicTypes.ts, 22, 39))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type TN4 = Uncapitalize<any>; // any
|
||||
type TN4 = Uncapitalize<any>; // Uncapitalize<`${any}`>
|
||||
>TN4 : Symbol(TN4, Decl(intrinsicTypes.ts, 23, 32))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
|
||||
@ -5,11 +5,11 @@ type TU1 = Uppercase<'hello'>; // "HELLO"
|
||||
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
|
||||
>TU2 : "FOO" | "BAR"
|
||||
|
||||
type TU3 = Uppercase<string>; // string
|
||||
>TU3 : string
|
||||
type TU3 = Uppercase<string>; // Uppercase<string>
|
||||
>TU3 : Uppercase<string>
|
||||
|
||||
type TU4 = Uppercase<any>; // any
|
||||
>TU4 : any
|
||||
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
|
||||
>TU4 : Uppercase<`${any}`>
|
||||
|
||||
type TU5 = Uppercase<never>; // never
|
||||
>TU5 : never
|
||||
@ -23,11 +23,11 @@ type TL1 = Lowercase<'HELLO'>; // "hello"
|
||||
type TL2 = Lowercase<'FOO' | 'BAR'>; // "foo" | "bar"
|
||||
>TL2 : "foo" | "bar"
|
||||
|
||||
type TL3 = Lowercase<string>; // string
|
||||
>TL3 : string
|
||||
type TL3 = Lowercase<string>; // Lowercase<string>
|
||||
>TL3 : Lowercase<string>
|
||||
|
||||
type TL4 = Lowercase<any>; // any
|
||||
>TL4 : any
|
||||
type TL4 = Lowercase<any>; // Lowercase<`${any}`>
|
||||
>TL4 : Lowercase<`${any}`>
|
||||
|
||||
type TL5 = Lowercase<never>; // never
|
||||
>TL5 : never
|
||||
@ -41,11 +41,11 @@ type TC1 = Capitalize<'hello'>; // "Hello"
|
||||
type TC2 = Capitalize<'foo' | 'bar'>; // "Foo" | "Bar"
|
||||
>TC2 : "Foo" | "Bar"
|
||||
|
||||
type TC3 = Capitalize<string>; // string
|
||||
>TC3 : string
|
||||
type TC3 = Capitalize<string>; // Capitalize<string>
|
||||
>TC3 : Capitalize<string>
|
||||
|
||||
type TC4 = Capitalize<any>; // any
|
||||
>TC4 : any
|
||||
type TC4 = Capitalize<any>; // Capitalize<`${any}`>
|
||||
>TC4 : Capitalize<`${any}`>
|
||||
|
||||
type TC5 = Capitalize<never>; // never
|
||||
>TC5 : never
|
||||
@ -59,11 +59,11 @@ type TN1 = Uncapitalize<'Hello'>; // "hello"
|
||||
type TN2 = Uncapitalize<'Foo' | 'Bar'>; // "foo" | "bar"
|
||||
>TN2 : "foo" | "bar"
|
||||
|
||||
type TN3 = Uncapitalize<string>; // string
|
||||
>TN3 : string
|
||||
type TN3 = Uncapitalize<string>; // Uncapitalize<string>
|
||||
>TN3 : Uncapitalize<string>
|
||||
|
||||
type TN4 = Uncapitalize<any>; // any
|
||||
>TN4 : any
|
||||
type TN4 = Uncapitalize<any>; // Uncapitalize<`${any}`>
|
||||
>TN4 : Uncapitalize<`${any}`>
|
||||
|
||||
type TN5 = Uncapitalize<never>; // never
|
||||
>TN5 : never
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
tests/cases/conformance/types/mapped/mappedTypeConstraints2.ts(10,11): error TS2322: Type 'Mapped2<K>[`get${K}`]' is not assignable to type '{ a: K; }'.
|
||||
Type 'Mapped2<K>[`get${string}`]' is not assignable to type '{ a: K; }'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeConstraints2.ts(16,11): error TS2322: Type 'Mapped3<K>[Uppercase<K>]' is not assignable to type '{ a: K; }'.
|
||||
Type 'Mapped3<K>[string]' is not assignable to type '{ a: K; }'.
|
||||
Type 'Mapped3<K>[Uppercase<string>]' is not assignable to type '{ a: K; }'.
|
||||
Type 'Mapped3<K>[string]' is not assignable to type '{ a: K; }'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeConstraints2.ts(25,57): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
|
||||
'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'.
|
||||
|
||||
@ -28,7 +29,8 @@ tests/cases/conformance/types/mapped/mappedTypeConstraints2.ts(25,57): error TS2
|
||||
const x: { a: K } = obj[key]; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Mapped3<K>[Uppercase<K>]' is not assignable to type '{ a: K; }'.
|
||||
!!! error TS2322: Type 'Mapped3<K>[string]' is not assignable to type '{ a: K; }'.
|
||||
!!! error TS2322: Type 'Mapped3<K>[Uppercase<string>]' is not assignable to type '{ a: K; }'.
|
||||
!!! error TS2322: Type 'Mapped3<K>[string]' is not assignable to type '{ a: K; }'.
|
||||
}
|
||||
|
||||
// Repro from #47794
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts(7,1): error TS2322: Type 'string' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts(15,1): error TS2322: Type 'string' is not assignable to type 'Uppercase<`${Lowercase<`${number}`>}`>'.
|
||||
tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts(16,1): error TS2322: Type 'string' is not assignable to type 'Uppercase<`${Lowercase<`${number}`>}`>'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts (3 errors) ====
|
||||
declare var x: Uppercase<Lowercase<string>>;
|
||||
|
||||
// good
|
||||
x = "A";
|
||||
|
||||
// bad
|
||||
x = "a";
|
||||
~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
|
||||
declare var y: Uppercase<Lowercase<`${number}`>>;
|
||||
|
||||
// good
|
||||
y = "1";
|
||||
|
||||
// bad
|
||||
y = "a";
|
||||
~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<`${Lowercase<`${number}`>}`>'.
|
||||
y = "A";
|
||||
~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<`${Lowercase<`${number}`>}`>'.
|
||||
@ -0,0 +1,28 @@
|
||||
//// [stringLiteralsAssignedToStringMappings.ts]
|
||||
declare var x: Uppercase<Lowercase<string>>;
|
||||
|
||||
// good
|
||||
x = "A";
|
||||
|
||||
// bad
|
||||
x = "a";
|
||||
|
||||
declare var y: Uppercase<Lowercase<`${number}`>>;
|
||||
|
||||
// good
|
||||
y = "1";
|
||||
|
||||
// bad
|
||||
y = "a";
|
||||
y = "A";
|
||||
|
||||
//// [stringLiteralsAssignedToStringMappings.js]
|
||||
// good
|
||||
x = "A";
|
||||
// bad
|
||||
x = "a";
|
||||
// good
|
||||
y = "1";
|
||||
// bad
|
||||
y = "a";
|
||||
y = "A";
|
||||
@ -0,0 +1,30 @@
|
||||
=== tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts ===
|
||||
declare var x: Uppercase<Lowercase<string>>;
|
||||
>x : Symbol(x, Decl(stringLiteralsAssignedToStringMappings.ts, 0, 11))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// good
|
||||
x = "A";
|
||||
>x : Symbol(x, Decl(stringLiteralsAssignedToStringMappings.ts, 0, 11))
|
||||
|
||||
// bad
|
||||
x = "a";
|
||||
>x : Symbol(x, Decl(stringLiteralsAssignedToStringMappings.ts, 0, 11))
|
||||
|
||||
declare var y: Uppercase<Lowercase<`${number}`>>;
|
||||
>y : Symbol(y, Decl(stringLiteralsAssignedToStringMappings.ts, 8, 11))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// good
|
||||
y = "1";
|
||||
>y : Symbol(y, Decl(stringLiteralsAssignedToStringMappings.ts, 8, 11))
|
||||
|
||||
// bad
|
||||
y = "a";
|
||||
>y : Symbol(y, Decl(stringLiteralsAssignedToStringMappings.ts, 8, 11))
|
||||
|
||||
y = "A";
|
||||
>y : Symbol(y, Decl(stringLiteralsAssignedToStringMappings.ts, 8, 11))
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
=== tests/cases/conformance/types/literal/stringLiteralsAssignedToStringMappings.ts ===
|
||||
declare var x: Uppercase<Lowercase<string>>;
|
||||
>x : Uppercase<Lowercase<string>>
|
||||
|
||||
// good
|
||||
x = "A";
|
||||
>x = "A" : "A"
|
||||
>x : Uppercase<Lowercase<string>>
|
||||
>"A" : "A"
|
||||
|
||||
// bad
|
||||
x = "a";
|
||||
>x = "a" : "a"
|
||||
>x : Uppercase<Lowercase<string>>
|
||||
>"a" : "a"
|
||||
|
||||
declare var y: Uppercase<Lowercase<`${number}`>>;
|
||||
>y : Uppercase<`${Lowercase<`${number}`>}`>
|
||||
|
||||
// good
|
||||
y = "1";
|
||||
>y = "1" : "1"
|
||||
>y : Uppercase<`${Lowercase<`${number}`>}`>
|
||||
>"1" : "1"
|
||||
|
||||
// bad
|
||||
y = "a";
|
||||
>y = "a" : "a"
|
||||
>y : Uppercase<`${Lowercase<`${number}`>}`>
|
||||
>"a" : "a"
|
||||
|
||||
y = "A";
|
||||
>y = "A" : "A"
|
||||
>y : Uppercase<`${Lowercase<`${number}`>}`>
|
||||
>"A" : "A"
|
||||
|
||||
@ -0,0 +1,250 @@
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(25,5): error TS2322: Type '`aA${string}`' is not assignable to type '"aA"'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(26,5): error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '"AA"'.
|
||||
Type '`AA${string}`' is not assignable to type '"AA"'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(27,5): error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '"aa"'.
|
||||
Type '`aa${string}`' is not assignable to type '"aa"'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(30,5): error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '`aA${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(31,5): error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '`aA${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(33,5): error TS2322: Type '`aA${string}`' is not assignable to type '`AA${Uppercase<string>}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(34,5): error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '`AA${Uppercase<string>}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(36,5): error TS2322: Type '`aA${string}`' is not assignable to type '`aa${Lowercase<string>}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(37,5): error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '`aa${Lowercase<string>}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(51,5): error TS2322: Type 'string' is not assignable to type 'Uppercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(52,5): error TS2322: Type 'Lowercase<string>' is not assignable to type 'Uppercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(53,5): error TS2322: Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(54,5): error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(56,5): error TS2322: Type 'string' is not assignable to type 'Uppercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(57,5): error TS2322: Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(78,5): error TS2322: Type 'Uppercase<string>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(79,5): error TS2322: Type 'Uppercase<string>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(83,5): error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(84,5): error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<string>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(85,5): error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(87,5): error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(88,5): error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(89,5): error TS2322: Type 'Uppercase<Lowercase<string>>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(129,5): error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
Type 'string' is not assignable to type '`A${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(130,5): error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(131,5): error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(147,5): error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
Type 'string' is not assignable to type '`a${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(148,5): error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts(149,5): error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts (29 errors) ====
|
||||
// non-template
|
||||
type A = "aA";
|
||||
type B = Uppercase<A>;
|
||||
type C = Lowercase<A>;
|
||||
|
||||
// templated
|
||||
type ATemplate = `aA${string}`;
|
||||
type BTemplate = Uppercase<ATemplate>;
|
||||
type CTemplate = Lowercase<ATemplate>;
|
||||
|
||||
function f1(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
a_template: ATemplate,
|
||||
b_template: BTemplate,
|
||||
c_template: CTemplate
|
||||
) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
b_template = b;
|
||||
c_template = c;
|
||||
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
~
|
||||
!!! error TS2322: Type '`aA${string}`' is not assignable to type '"aA"'.
|
||||
b = b_template;
|
||||
~
|
||||
!!! error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '"AA"'.
|
||||
!!! error TS2322: Type '`AA${string}`' is not assignable to type '"AA"'.
|
||||
c = c_template;
|
||||
~
|
||||
!!! error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '"aa"'.
|
||||
!!! error TS2322: Type '`aa${string}`' is not assignable to type '"aa"'.
|
||||
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '`aA${string}`'.
|
||||
a_template = c_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '`aA${string}`'.
|
||||
|
||||
b_template = a_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`aA${string}`' is not assignable to type '`AA${Uppercase<string>}`'.
|
||||
b_template = c_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`aa${Lowercase<string>}`' is not assignable to type '`AA${Uppercase<string>}`'.
|
||||
|
||||
c_template = a_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`aA${string}`' is not assignable to type '`aa${Lowercase<string>}`'.
|
||||
c_template = b_template;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '`AA${Uppercase<string>}`' is not assignable to type '`aa${Lowercase<string>}`'.
|
||||
}
|
||||
|
||||
// Raw string mapping assignability
|
||||
|
||||
function f2(x1: string, x2: Uppercase<string>, x3: Lowercase<string>) {
|
||||
// ok
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = "ABC";
|
||||
x3 = "abc";
|
||||
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<string>'.
|
||||
x2 = x3;
|
||||
~~
|
||||
!!! error TS2322: Type 'Lowercase<string>' is not assignable to type 'Uppercase<string>'.
|
||||
x3 = x1;
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
x3 = x2;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<string>'.
|
||||
|
||||
x2 = "AbC";
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<string>'.
|
||||
x3 = "AbC";
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
}
|
||||
|
||||
// Mappings over mappings
|
||||
|
||||
function f3(
|
||||
x1: Uppercase<string>,
|
||||
x2: Uppercase<Uppercase<string>>,
|
||||
x3: Uppercase<Lowercase<string>>) {
|
||||
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<string>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'Lowercase<string>'.
|
||||
x3 = x2;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<string>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
|
||||
// and this should also not be equivlent to any others
|
||||
var x4: Lowercase<Uppercase<string>> = null as any;
|
||||
x1 = x4;
|
||||
~~
|
||||
!!! error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<string>'.
|
||||
x2 = x4;
|
||||
~~
|
||||
!!! error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<string>'.
|
||||
x3 = x4;
|
||||
~~
|
||||
!!! error TS2322: Type 'Lowercase<Uppercase<string>>' is not assignable to type 'Uppercase<Lowercase<string>>'.
|
||||
|
||||
x4 = x1;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
x4 = x2;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<string>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
x4 = x3;
|
||||
~~
|
||||
!!! error TS2322: Type 'Uppercase<Lowercase<string>>' is not assignable to type 'Lowercase<Uppercase<string>>'.
|
||||
}
|
||||
|
||||
// string mapping over non-string pattern literals is preserved
|
||||
|
||||
type NonStringPat = Uppercase<`aA${number}${bigint}${boolean}`>;
|
||||
type EquivalentNonStringPat = `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}${Uppercase<`${boolean}`>}`;
|
||||
|
||||
function f4(x1: NonStringPat, x2: EquivalentNonStringPat) {
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
x2 = x1;
|
||||
}
|
||||
|
||||
// Capitalize and uncapitalize on template literals
|
||||
|
||||
function f5(
|
||||
cap_tem: `A${string}`,
|
||||
cap_str: Capitalize<string>,
|
||||
cap_tem_map: Capitalize<`A${string}`>,
|
||||
cap_tem_map2: Capitalize<`a${string}`>,
|
||||
uncap_tem: `a${string}`,
|
||||
uncap_str: Uncapitalize<string>,
|
||||
uncap_tem_map: Uncapitalize<`A${string}`>,
|
||||
uncap_tem_map2: Uncapitalize<`a${string}`>,
|
||||
) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
cap_str = cap_tem_map;
|
||||
cap_str = cap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
cap_tem = cap_tem_map2;
|
||||
cap_tem_map = cap_tem_map2;
|
||||
cap_tem_map = cap_tem;
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
cap_tem_map2 = cap_tem;
|
||||
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type '`A${string}`'.
|
||||
cap_tem_map = cap_str;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
cap_tem_map2 = cap_str;
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'Capitalize<string>' is not assignable to type '`A${string}`'.
|
||||
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
uncap_str = uncap_tem_map;
|
||||
uncap_str = uncap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
uncap_tem = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem;
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
~~~~~~~~~
|
||||
!!! error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type '`a${string}`'.
|
||||
uncap_tem_map = uncap_str;
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
uncap_tem_map2 = uncap_str;
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'Uncapitalize<string>' is not assignable to type '`a${string}`'.
|
||||
}
|
||||
245
tests/baselines/reference/stringMappingOverPatternLiterals.js
Normal file
245
tests/baselines/reference/stringMappingOverPatternLiterals.js
Normal file
@ -0,0 +1,245 @@
|
||||
//// [stringMappingOverPatternLiterals.ts]
|
||||
// non-template
|
||||
type A = "aA";
|
||||
type B = Uppercase<A>;
|
||||
type C = Lowercase<A>;
|
||||
|
||||
// templated
|
||||
type ATemplate = `aA${string}`;
|
||||
type BTemplate = Uppercase<ATemplate>;
|
||||
type CTemplate = Lowercase<ATemplate>;
|
||||
|
||||
function f1(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
a_template: ATemplate,
|
||||
b_template: BTemplate,
|
||||
c_template: CTemplate
|
||||
) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
b_template = b;
|
||||
c_template = c;
|
||||
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
b = b_template;
|
||||
c = c_template;
|
||||
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
a_template = c_template;
|
||||
|
||||
b_template = a_template;
|
||||
b_template = c_template;
|
||||
|
||||
c_template = a_template;
|
||||
c_template = b_template;
|
||||
}
|
||||
|
||||
// Raw string mapping assignability
|
||||
|
||||
function f2(x1: string, x2: Uppercase<string>, x3: Lowercase<string>) {
|
||||
// ok
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = "ABC";
|
||||
x3 = "abc";
|
||||
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
|
||||
x2 = "AbC";
|
||||
x3 = "AbC";
|
||||
}
|
||||
|
||||
// Mappings over mappings
|
||||
|
||||
function f3(
|
||||
x1: Uppercase<string>,
|
||||
x2: Uppercase<Uppercase<string>>,
|
||||
x3: Uppercase<Lowercase<string>>) {
|
||||
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
|
||||
// and this should also not be equivlent to any others
|
||||
var x4: Lowercase<Uppercase<string>> = null as any;
|
||||
x1 = x4;
|
||||
x2 = x4;
|
||||
x3 = x4;
|
||||
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
}
|
||||
|
||||
// string mapping over non-string pattern literals is preserved
|
||||
|
||||
type NonStringPat = Uppercase<`aA${number}${bigint}${boolean}`>;
|
||||
type EquivalentNonStringPat = `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}${Uppercase<`${boolean}`>}`;
|
||||
|
||||
function f4(x1: NonStringPat, x2: EquivalentNonStringPat) {
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
x2 = x1;
|
||||
}
|
||||
|
||||
// Capitalize and uncapitalize on template literals
|
||||
|
||||
function f5(
|
||||
cap_tem: `A${string}`,
|
||||
cap_str: Capitalize<string>,
|
||||
cap_tem_map: Capitalize<`A${string}`>,
|
||||
cap_tem_map2: Capitalize<`a${string}`>,
|
||||
uncap_tem: `a${string}`,
|
||||
uncap_str: Uncapitalize<string>,
|
||||
uncap_tem_map: Uncapitalize<`A${string}`>,
|
||||
uncap_tem_map2: Uncapitalize<`a${string}`>,
|
||||
) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
cap_str = cap_tem_map;
|
||||
cap_str = cap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
cap_tem = cap_tem_map2;
|
||||
cap_tem_map = cap_tem_map2;
|
||||
cap_tem_map = cap_tem;
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
cap_tem_map2 = cap_tem;
|
||||
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
cap_tem_map = cap_str;
|
||||
cap_tem_map2 = cap_str;
|
||||
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
uncap_str = uncap_tem_map;
|
||||
uncap_str = uncap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
uncap_tem = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem;
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
uncap_tem_map = uncap_str;
|
||||
uncap_tem_map2 = uncap_str;
|
||||
}
|
||||
|
||||
//// [stringMappingOverPatternLiterals.js]
|
||||
function f1(a, b, c, a_template, b_template, c_template) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
b_template = b;
|
||||
c_template = c;
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
b = b_template;
|
||||
c = c_template;
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
a_template = c_template;
|
||||
b_template = a_template;
|
||||
b_template = c_template;
|
||||
c_template = a_template;
|
||||
c_template = b_template;
|
||||
}
|
||||
// Raw string mapping assignability
|
||||
function f2(x1, x2, x3) {
|
||||
// ok
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x2 = "ABC";
|
||||
x3 = "abc";
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
x2 = "AbC";
|
||||
x3 = "AbC";
|
||||
}
|
||||
// Mappings over mappings
|
||||
function f3(x1, x2, x3) {
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
// and this should also not be equivlent to any others
|
||||
var x4 = null;
|
||||
x1 = x4;
|
||||
x2 = x4;
|
||||
x3 = x4;
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
}
|
||||
function f4(x1, x2) {
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
x2 = x1;
|
||||
}
|
||||
// Capitalize and uncapitalize on template literals
|
||||
function f5(cap_tem, cap_str, cap_tem_map, cap_tem_map2, uncap_tem, uncap_str, uncap_tem_map, uncap_tem_map2) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
cap_str = cap_tem_map;
|
||||
cap_str = cap_tem_map2;
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
cap_tem = cap_tem_map2;
|
||||
cap_tem_map = cap_tem_map2;
|
||||
cap_tem_map = cap_tem;
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
cap_tem_map2 = cap_tem;
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
cap_tem_map = cap_str;
|
||||
cap_tem_map2 = cap_str;
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
uncap_str = uncap_tem_map;
|
||||
uncap_str = uncap_tem_map2;
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
uncap_tem = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem;
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
uncap_tem_map = uncap_str;
|
||||
uncap_tem_map2 = uncap_str;
|
||||
}
|
||||
@ -0,0 +1,404 @@
|
||||
=== tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts ===
|
||||
// non-template
|
||||
type A = "aA";
|
||||
>A : Symbol(A, Decl(stringMappingOverPatternLiterals.ts, 0, 0))
|
||||
|
||||
type B = Uppercase<A>;
|
||||
>B : Symbol(B, Decl(stringMappingOverPatternLiterals.ts, 1, 14))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>A : Symbol(A, Decl(stringMappingOverPatternLiterals.ts, 0, 0))
|
||||
|
||||
type C = Lowercase<A>;
|
||||
>C : Symbol(C, Decl(stringMappingOverPatternLiterals.ts, 2, 22))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
>A : Symbol(A, Decl(stringMappingOverPatternLiterals.ts, 0, 0))
|
||||
|
||||
// templated
|
||||
type ATemplate = `aA${string}`;
|
||||
>ATemplate : Symbol(ATemplate, Decl(stringMappingOverPatternLiterals.ts, 3, 22))
|
||||
|
||||
type BTemplate = Uppercase<ATemplate>;
|
||||
>BTemplate : Symbol(BTemplate, Decl(stringMappingOverPatternLiterals.ts, 6, 31))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>ATemplate : Symbol(ATemplate, Decl(stringMappingOverPatternLiterals.ts, 3, 22))
|
||||
|
||||
type CTemplate = Lowercase<ATemplate>;
|
||||
>CTemplate : Symbol(CTemplate, Decl(stringMappingOverPatternLiterals.ts, 7, 38))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
>ATemplate : Symbol(ATemplate, Decl(stringMappingOverPatternLiterals.ts, 3, 22))
|
||||
|
||||
function f1(
|
||||
>f1 : Symbol(f1, Decl(stringMappingOverPatternLiterals.ts, 8, 38))
|
||||
|
||||
a: A,
|
||||
>a : Symbol(a, Decl(stringMappingOverPatternLiterals.ts, 10, 12))
|
||||
>A : Symbol(A, Decl(stringMappingOverPatternLiterals.ts, 0, 0))
|
||||
|
||||
b: B,
|
||||
>b : Symbol(b, Decl(stringMappingOverPatternLiterals.ts, 11, 9))
|
||||
>B : Symbol(B, Decl(stringMappingOverPatternLiterals.ts, 1, 14))
|
||||
|
||||
c: C,
|
||||
>c : Symbol(c, Decl(stringMappingOverPatternLiterals.ts, 12, 9))
|
||||
>C : Symbol(C, Decl(stringMappingOverPatternLiterals.ts, 2, 22))
|
||||
|
||||
a_template: ATemplate,
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
>ATemplate : Symbol(ATemplate, Decl(stringMappingOverPatternLiterals.ts, 3, 22))
|
||||
|
||||
b_template: BTemplate,
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
>BTemplate : Symbol(BTemplate, Decl(stringMappingOverPatternLiterals.ts, 6, 31))
|
||||
|
||||
c_template: CTemplate
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
>CTemplate : Symbol(CTemplate, Decl(stringMappingOverPatternLiterals.ts, 7, 38))
|
||||
|
||||
) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
>a : Symbol(a, Decl(stringMappingOverPatternLiterals.ts, 10, 12))
|
||||
|
||||
b_template = b;
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
>b : Symbol(b, Decl(stringMappingOverPatternLiterals.ts, 11, 9))
|
||||
|
||||
c_template = c;
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
>c : Symbol(c, Decl(stringMappingOverPatternLiterals.ts, 12, 9))
|
||||
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
>a : Symbol(a, Decl(stringMappingOverPatternLiterals.ts, 10, 12))
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
|
||||
b = b_template;
|
||||
>b : Symbol(b, Decl(stringMappingOverPatternLiterals.ts, 11, 9))
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
|
||||
c = c_template;
|
||||
>c : Symbol(c, Decl(stringMappingOverPatternLiterals.ts, 12, 9))
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
|
||||
a_template = c_template;
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
|
||||
b_template = a_template;
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
|
||||
b_template = c_template;
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
|
||||
c_template = a_template;
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
>a_template : Symbol(a_template, Decl(stringMappingOverPatternLiterals.ts, 13, 9))
|
||||
|
||||
c_template = b_template;
|
||||
>c_template : Symbol(c_template, Decl(stringMappingOverPatternLiterals.ts, 15, 26))
|
||||
>b_template : Symbol(b_template, Decl(stringMappingOverPatternLiterals.ts, 14, 26))
|
||||
}
|
||||
|
||||
// Raw string mapping assignability
|
||||
|
||||
function f2(x1: string, x2: Uppercase<string>, x3: Lowercase<string>) {
|
||||
>f2 : Symbol(f2, Decl(stringMappingOverPatternLiterals.ts, 37, 1))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 41, 12))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
x1 = x2;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 41, 12))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
|
||||
x1 = x3;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 41, 12))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
|
||||
x2 = "ABC";
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
|
||||
x3 = "abc";
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 41, 12))
|
||||
|
||||
x2 = x3;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
|
||||
x3 = x1;
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 41, 12))
|
||||
|
||||
x3 = x2;
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
|
||||
x2 = "AbC";
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 41, 23))
|
||||
|
||||
x3 = "AbC";
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 41, 46))
|
||||
}
|
||||
|
||||
// Mappings over mappings
|
||||
|
||||
function f3(
|
||||
>f3 : Symbol(f3, Decl(stringMappingOverPatternLiterals.ts, 57, 1))
|
||||
|
||||
x1: Uppercase<string>,
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
x2: Uppercase<Uppercase<string>>,
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
x3: Uppercase<Lowercase<string>>) {
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
|
||||
x1 = x3;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
|
||||
x2 = x1;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
|
||||
x2 = x3;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
|
||||
x3 = x2;
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
|
||||
// and this should also not be equivlent to any others
|
||||
var x4: Lowercase<Uppercase<string>> = null as any;
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
x1 = x4;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
|
||||
x2 = x4;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
|
||||
x3 = x4;
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
|
||||
x4 = x1;
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 61, 12))
|
||||
|
||||
x4 = x2;
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 62, 26))
|
||||
|
||||
x4 = x3;
|
||||
>x4 : Symbol(x4, Decl(stringMappingOverPatternLiterals.ts, 81, 7))
|
||||
>x3 : Symbol(x3, Decl(stringMappingOverPatternLiterals.ts, 63, 37))
|
||||
}
|
||||
|
||||
// string mapping over non-string pattern literals is preserved
|
||||
|
||||
type NonStringPat = Uppercase<`aA${number}${bigint}${boolean}`>;
|
||||
>NonStringPat : Symbol(NonStringPat, Decl(stringMappingOverPatternLiterals.ts, 89, 1))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type EquivalentNonStringPat = `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}${Uppercase<`${boolean}`>}`;
|
||||
>EquivalentNonStringPat : Symbol(EquivalentNonStringPat, Decl(stringMappingOverPatternLiterals.ts, 93, 64))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
function f4(x1: NonStringPat, x2: EquivalentNonStringPat) {
|
||||
>f4 : Symbol(f4, Decl(stringMappingOverPatternLiterals.ts, 94, 111))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 96, 12))
|
||||
>NonStringPat : Symbol(NonStringPat, Decl(stringMappingOverPatternLiterals.ts, 89, 1))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 96, 29))
|
||||
>EquivalentNonStringPat : Symbol(EquivalentNonStringPat, Decl(stringMappingOverPatternLiterals.ts, 93, 64))
|
||||
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 96, 12))
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 96, 29))
|
||||
|
||||
x2 = x1;
|
||||
>x2 : Symbol(x2, Decl(stringMappingOverPatternLiterals.ts, 96, 29))
|
||||
>x1 : Symbol(x1, Decl(stringMappingOverPatternLiterals.ts, 96, 12))
|
||||
}
|
||||
|
||||
// Capitalize and uncapitalize on template literals
|
||||
|
||||
function f5(
|
||||
>f5 : Symbol(f5, Decl(stringMappingOverPatternLiterals.ts, 100, 1))
|
||||
|
||||
cap_tem: `A${string}`,
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
|
||||
cap_str: Capitalize<string>,
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
cap_tem_map: Capitalize<`A${string}`>,
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
cap_tem_map2: Capitalize<`a${string}`>,
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
uncap_tem: `a${string}`,
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
|
||||
uncap_str: Uncapitalize<string>,
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
uncap_tem_map: Uncapitalize<`A${string}`>,
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
uncap_tem_map2: Uncapitalize<`a${string}`>,
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
>Uncapitalize : Symbol(Uncapitalize, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
|
||||
cap_str = cap_tem_map;
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
|
||||
cap_str = cap_tem_map2;
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
|
||||
cap_tem = cap_tem_map2;
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
|
||||
cap_tem_map = cap_tem_map2;
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
|
||||
cap_tem_map = cap_tem;
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
|
||||
cap_tem_map2 = cap_tem;
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
>cap_tem : Symbol(cap_tem, Decl(stringMappingOverPatternLiterals.ts, 104, 12))
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
|
||||
cap_tem_map = cap_str;
|
||||
>cap_tem_map : Symbol(cap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 106, 32))
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
|
||||
cap_tem_map2 = cap_str;
|
||||
>cap_tem_map2 : Symbol(cap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 107, 42))
|
||||
>cap_str : Symbol(cap_str, Decl(stringMappingOverPatternLiterals.ts, 105, 26))
|
||||
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
|
||||
uncap_str = uncap_tem_map;
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
|
||||
uncap_str = uncap_tem_map2;
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
|
||||
uncap_tem = uncap_tem_map2;
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
|
||||
uncap_tem_map = uncap_tem;
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
>uncap_tem : Symbol(uncap_tem, Decl(stringMappingOverPatternLiterals.ts, 108, 43))
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
|
||||
uncap_tem_map = uncap_str;
|
||||
>uncap_tem_map : Symbol(uncap_tem_map, Decl(stringMappingOverPatternLiterals.ts, 110, 36))
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
|
||||
uncap_tem_map2 = uncap_str;
|
||||
>uncap_tem_map2 : Symbol(uncap_tem_map2, Decl(stringMappingOverPatternLiterals.ts, 111, 46))
|
||||
>uncap_str : Symbol(uncap_str, Decl(stringMappingOverPatternLiterals.ts, 109, 28))
|
||||
}
|
||||
435
tests/baselines/reference/stringMappingOverPatternLiterals.types
Normal file
435
tests/baselines/reference/stringMappingOverPatternLiterals.types
Normal file
@ -0,0 +1,435 @@
|
||||
=== tests/cases/conformance/types/literal/stringMappingOverPatternLiterals.ts ===
|
||||
// non-template
|
||||
type A = "aA";
|
||||
>A : "aA"
|
||||
|
||||
type B = Uppercase<A>;
|
||||
>B : "AA"
|
||||
|
||||
type C = Lowercase<A>;
|
||||
>C : "aa"
|
||||
|
||||
// templated
|
||||
type ATemplate = `aA${string}`;
|
||||
>ATemplate : `aA${string}`
|
||||
|
||||
type BTemplate = Uppercase<ATemplate>;
|
||||
>BTemplate : `AA${Uppercase<string>}`
|
||||
|
||||
type CTemplate = Lowercase<ATemplate>;
|
||||
>CTemplate : `aa${Lowercase<string>}`
|
||||
|
||||
function f1(
|
||||
>f1 : (a: A, b: B, c: C, a_template: ATemplate, b_template: BTemplate, c_template: CTemplate) => void
|
||||
|
||||
a: A,
|
||||
>a : "aA"
|
||||
|
||||
b: B,
|
||||
>b : "AA"
|
||||
|
||||
c: C,
|
||||
>c : "aa"
|
||||
|
||||
a_template: ATemplate,
|
||||
>a_template : `aA${string}`
|
||||
|
||||
b_template: BTemplate,
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
|
||||
c_template: CTemplate
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
|
||||
) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
>a_template = a : "aA"
|
||||
>a_template : `aA${string}`
|
||||
>a : "aA"
|
||||
|
||||
b_template = b;
|
||||
>b_template = b : "AA"
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
>b : "AA"
|
||||
|
||||
c_template = c;
|
||||
>c_template = c : "aa"
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
>c : "aa"
|
||||
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
>a = a_template : `aA${string}`
|
||||
>a : "aA"
|
||||
>a_template : `aA${string}`
|
||||
|
||||
b = b_template;
|
||||
>b = b_template : `AA${Uppercase<string>}`
|
||||
>b : "AA"
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
|
||||
c = c_template;
|
||||
>c = c_template : `aa${Lowercase<string>}`
|
||||
>c : "aa"
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
>a_template = b_template : `AA${Uppercase<string>}`
|
||||
>a_template : `aA${string}`
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
|
||||
a_template = c_template;
|
||||
>a_template = c_template : `aa${Lowercase<string>}`
|
||||
>a_template : `aA${string}`
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
|
||||
b_template = a_template;
|
||||
>b_template = a_template : `aA${string}`
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
>a_template : `aA${string}`
|
||||
|
||||
b_template = c_template;
|
||||
>b_template = c_template : `aa${Lowercase<string>}`
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
|
||||
c_template = a_template;
|
||||
>c_template = a_template : `aA${string}`
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
>a_template : `aA${string}`
|
||||
|
||||
c_template = b_template;
|
||||
>c_template = b_template : `AA${Uppercase<string>}`
|
||||
>c_template : `aa${Lowercase<string>}`
|
||||
>b_template : `AA${Uppercase<string>}`
|
||||
}
|
||||
|
||||
// Raw string mapping assignability
|
||||
|
||||
function f2(x1: string, x2: Uppercase<string>, x3: Lowercase<string>) {
|
||||
>f2 : (x1: string, x2: Uppercase<string>, x3: Lowercase<string>) => void
|
||||
>x1 : string
|
||||
>x2 : Uppercase<string>
|
||||
>x3 : Lowercase<string>
|
||||
|
||||
// ok
|
||||
x1 = x2;
|
||||
>x1 = x2 : Uppercase<string>
|
||||
>x1 : string
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
x1 = x3;
|
||||
>x1 = x3 : Lowercase<string>
|
||||
>x1 : string
|
||||
>x3 : Lowercase<string>
|
||||
|
||||
x2 = "ABC";
|
||||
>x2 = "ABC" : "ABC"
|
||||
>x2 : Uppercase<string>
|
||||
>"ABC" : "ABC"
|
||||
|
||||
x3 = "abc";
|
||||
>x3 = "abc" : "abc"
|
||||
>x3 : Lowercase<string>
|
||||
>"abc" : "abc"
|
||||
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
>x2 = x1 : string
|
||||
>x2 : Uppercase<string>
|
||||
>x1 : string
|
||||
|
||||
x2 = x3;
|
||||
>x2 = x3 : Lowercase<string>
|
||||
>x2 : Uppercase<string>
|
||||
>x3 : Lowercase<string>
|
||||
|
||||
x3 = x1;
|
||||
>x3 = x1 : string
|
||||
>x3 : Lowercase<string>
|
||||
>x1 : string
|
||||
|
||||
x3 = x2;
|
||||
>x3 = x2 : Uppercase<string>
|
||||
>x3 : Lowercase<string>
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
x2 = "AbC";
|
||||
>x2 = "AbC" : "AbC"
|
||||
>x2 : Uppercase<string>
|
||||
>"AbC" : "AbC"
|
||||
|
||||
x3 = "AbC";
|
||||
>x3 = "AbC" : "AbC"
|
||||
>x3 : Lowercase<string>
|
||||
>"AbC" : "AbC"
|
||||
}
|
||||
|
||||
// Mappings over mappings
|
||||
|
||||
function f3(
|
||||
>f3 : (x1: Uppercase<string>, x2: Uppercase<Uppercase<string>>, x3: Uppercase<Lowercase<string>>) => void
|
||||
|
||||
x1: Uppercase<string>,
|
||||
>x1 : Uppercase<string>
|
||||
|
||||
x2: Uppercase<Uppercase<string>>,
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
x3: Uppercase<Lowercase<string>>) {
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
>x1 = x2 : Uppercase<string>
|
||||
>x1 : Uppercase<string>
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
x1 = x3;
|
||||
>x1 = x3 : Uppercase<Lowercase<string>>
|
||||
>x1 : Uppercase<string>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
|
||||
x2 = x1;
|
||||
>x2 = x1 : Uppercase<string>
|
||||
>x2 : Uppercase<string>
|
||||
>x1 : Uppercase<string>
|
||||
|
||||
x2 = x3;
|
||||
>x2 = x3 : Uppercase<Lowercase<string>>
|
||||
>x2 : Uppercase<string>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
>x3 = x1 : Uppercase<string>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
>x1 : Uppercase<string>
|
||||
|
||||
x3 = x2;
|
||||
>x3 = x2 : Uppercase<string>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
// and this should also not be equivlent to any others
|
||||
var x4: Lowercase<Uppercase<string>> = null as any;
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
>null as any : any
|
||||
>null : null
|
||||
|
||||
x1 = x4;
|
||||
>x1 = x4 : Lowercase<Uppercase<string>>
|
||||
>x1 : Uppercase<string>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
|
||||
x2 = x4;
|
||||
>x2 = x4 : Lowercase<Uppercase<string>>
|
||||
>x2 : Uppercase<string>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
|
||||
x3 = x4;
|
||||
>x3 = x4 : Lowercase<Uppercase<string>>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
|
||||
x4 = x1;
|
||||
>x4 = x1 : Uppercase<string>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
>x1 : Uppercase<string>
|
||||
|
||||
x4 = x2;
|
||||
>x4 = x2 : Uppercase<string>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
>x2 : Uppercase<string>
|
||||
|
||||
x4 = x3;
|
||||
>x4 = x3 : Uppercase<Lowercase<string>>
|
||||
>x4 : Lowercase<Uppercase<string>>
|
||||
>x3 : Uppercase<Lowercase<string>>
|
||||
}
|
||||
|
||||
// string mapping over non-string pattern literals is preserved
|
||||
|
||||
type NonStringPat = Uppercase<`aA${number}${bigint}${boolean}`>;
|
||||
>NonStringPat : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
|
||||
type EquivalentNonStringPat = `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}${Uppercase<`${boolean}`>}`;
|
||||
>EquivalentNonStringPat : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
|
||||
function f4(x1: NonStringPat, x2: EquivalentNonStringPat) {
|
||||
>f4 : (x1: NonStringPat, x2: EquivalentNonStringPat) => void
|
||||
>x1 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
>x2 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
>x1 = x2 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
>x1 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
>x2 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
|
||||
x2 = x1;
|
||||
>x2 = x1 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
>x2 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
>x1 : `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}FALSE` | `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}TRUE`
|
||||
}
|
||||
|
||||
// Capitalize and uncapitalize on template literals
|
||||
|
||||
function f5(
|
||||
>f5 : (cap_tem: `A${string}`, cap_str: Capitalize<string>, cap_tem_map: Capitalize<`A${string}`>, cap_tem_map2: Capitalize<`a${string}`>, uncap_tem: `a${string}`, uncap_str: Uncapitalize<string>, uncap_tem_map: Uncapitalize<`A${string}`>, uncap_tem_map2: Uncapitalize<`a${string}`>) => void
|
||||
|
||||
cap_tem: `A${string}`,
|
||||
>cap_tem : `A${string}`
|
||||
|
||||
cap_str: Capitalize<string>,
|
||||
>cap_str : Capitalize<string>
|
||||
|
||||
cap_tem_map: Capitalize<`A${string}`>,
|
||||
>cap_tem_map : `A${string}`
|
||||
|
||||
cap_tem_map2: Capitalize<`a${string}`>,
|
||||
>cap_tem_map2 : `A${string}`
|
||||
|
||||
uncap_tem: `a${string}`,
|
||||
>uncap_tem : `a${string}`
|
||||
|
||||
uncap_str: Uncapitalize<string>,
|
||||
>uncap_str : Uncapitalize<string>
|
||||
|
||||
uncap_tem_map: Uncapitalize<`A${string}`>,
|
||||
>uncap_tem_map : `a${string}`
|
||||
|
||||
uncap_tem_map2: Uncapitalize<`a${string}`>,
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
|
||||
) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
>cap_str = cap_tem : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
>cap_tem : `A${string}`
|
||||
|
||||
cap_str = cap_tem_map;
|
||||
>cap_str = cap_tem_map : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
>cap_tem_map : `A${string}`
|
||||
|
||||
cap_str = cap_tem_map2;
|
||||
>cap_str = cap_tem_map2 : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
>cap_tem_map2 : `A${string}`
|
||||
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
>cap_tem = cap_tem_map : `A${string}`
|
||||
>cap_tem : `A${string}`
|
||||
>cap_tem_map : `A${string}`
|
||||
|
||||
cap_tem = cap_tem_map2;
|
||||
>cap_tem = cap_tem_map2 : `A${string}`
|
||||
>cap_tem : `A${string}`
|
||||
>cap_tem_map2 : `A${string}`
|
||||
|
||||
cap_tem_map = cap_tem_map2;
|
||||
>cap_tem_map = cap_tem_map2 : `A${string}`
|
||||
>cap_tem_map : `A${string}`
|
||||
>cap_tem_map2 : `A${string}`
|
||||
|
||||
cap_tem_map = cap_tem;
|
||||
>cap_tem_map = cap_tem : `A${string}`
|
||||
>cap_tem_map : `A${string}`
|
||||
>cap_tem : `A${string}`
|
||||
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
>cap_tem_map2 = cap_tem_map : `A${string}`
|
||||
>cap_tem_map2 : `A${string}`
|
||||
>cap_tem_map : `A${string}`
|
||||
|
||||
cap_tem_map2 = cap_tem;
|
||||
>cap_tem_map2 = cap_tem : `A${string}`
|
||||
>cap_tem_map2 : `A${string}`
|
||||
>cap_tem : `A${string}`
|
||||
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
>cap_tem = cap_str : Capitalize<string>
|
||||
>cap_tem : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
|
||||
cap_tem_map = cap_str;
|
||||
>cap_tem_map = cap_str : Capitalize<string>
|
||||
>cap_tem_map : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
|
||||
cap_tem_map2 = cap_str;
|
||||
>cap_tem_map2 = cap_str : Capitalize<string>
|
||||
>cap_tem_map2 : `A${string}`
|
||||
>cap_str : Capitalize<string>
|
||||
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
>uncap_str = uncap_tem : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
>uncap_tem : `a${string}`
|
||||
|
||||
uncap_str = uncap_tem_map;
|
||||
>uncap_str = uncap_tem_map : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
>uncap_tem_map : `a${string}`
|
||||
|
||||
uncap_str = uncap_tem_map2;
|
||||
>uncap_str = uncap_tem_map2 : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
>uncap_tem = uncap_tem_map : `a${string}`
|
||||
>uncap_tem : `a${string}`
|
||||
>uncap_tem_map : `a${string}`
|
||||
|
||||
uncap_tem = uncap_tem_map2;
|
||||
>uncap_tem = uncap_tem_map2 : `a${string}`
|
||||
>uncap_tem : `a${string}`
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
>uncap_tem_map = uncap_tem_map2 : `a${string}`
|
||||
>uncap_tem_map : `a${string}`
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
|
||||
uncap_tem_map = uncap_tem;
|
||||
>uncap_tem_map = uncap_tem : `a${string}`
|
||||
>uncap_tem_map : `a${string}`
|
||||
>uncap_tem : `a${string}`
|
||||
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
>uncap_tem_map2 = uncap_tem_map : `a${string}`
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
>uncap_tem_map : `a${string}`
|
||||
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
>uncap_tem_map2 = uncap_tem : `a${string}`
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
>uncap_tem : `a${string}`
|
||||
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
>uncap_tem = uncap_str : Uncapitalize<string>
|
||||
>uncap_tem : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
|
||||
uncap_tem_map = uncap_str;
|
||||
>uncap_tem_map = uncap_str : Uncapitalize<string>
|
||||
>uncap_tem_map : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
|
||||
uncap_tem_map2 = uncap_str;
|
||||
>uncap_tem_map2 = uncap_str : Uncapitalize<string>
|
||||
>uncap_tem_map2 : `a${string}`
|
||||
>uncap_str : Uncapitalize<string>
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
declare var x: Uppercase<Lowercase<string>>;
|
||||
|
||||
// good
|
||||
x = "A";
|
||||
|
||||
// bad
|
||||
x = "a";
|
||||
|
||||
declare var y: Uppercase<Lowercase<`${number}`>>;
|
||||
|
||||
// good
|
||||
y = "1";
|
||||
|
||||
// bad
|
||||
y = "a";
|
||||
y = "A";
|
||||
@ -0,0 +1,150 @@
|
||||
// non-template
|
||||
type A = "aA";
|
||||
type B = Uppercase<A>;
|
||||
type C = Lowercase<A>;
|
||||
|
||||
// templated
|
||||
type ATemplate = `aA${string}`;
|
||||
type BTemplate = Uppercase<ATemplate>;
|
||||
type CTemplate = Lowercase<ATemplate>;
|
||||
|
||||
function f1(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
a_template: ATemplate,
|
||||
b_template: BTemplate,
|
||||
c_template: CTemplate
|
||||
) {
|
||||
// non-template versions should be assignable to templated versions (empty string matches string)
|
||||
a_template = a;
|
||||
b_template = b;
|
||||
c_template = c;
|
||||
|
||||
// not the other way around
|
||||
a = a_template;
|
||||
b = b_template;
|
||||
c = c_template;
|
||||
|
||||
// Additionally, all the template versions should be mutually incompatible (they describe differing sets)
|
||||
a_template = b_template;
|
||||
a_template = c_template;
|
||||
|
||||
b_template = a_template;
|
||||
b_template = c_template;
|
||||
|
||||
c_template = a_template;
|
||||
c_template = b_template;
|
||||
}
|
||||
|
||||
// Raw string mapping assignability
|
||||
|
||||
function f2(x1: string, x2: Uppercase<string>, x3: Lowercase<string>) {
|
||||
// ok
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = "ABC";
|
||||
x3 = "abc";
|
||||
|
||||
// should fail (sets do not match)
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
|
||||
x2 = "AbC";
|
||||
x3 = "AbC";
|
||||
}
|
||||
|
||||
// Mappings over mappings
|
||||
|
||||
function f3(
|
||||
x1: Uppercase<string>,
|
||||
x2: Uppercase<Uppercase<string>>,
|
||||
x3: Uppercase<Lowercase<string>>) {
|
||||
|
||||
// _ideally_ these would all be equivalent
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
|
||||
// you'd think these were equivalent - the outer `Uppercase` conceptually
|
||||
// makes the inner `Lowercase` effectively a noop - but that's not so;
|
||||
// the german sharp s makes that not completely true (lowercases to ss,
|
||||
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
|
||||
// and this should also not be equivlent to any others
|
||||
var x4: Lowercase<Uppercase<string>> = null as any;
|
||||
x1 = x4;
|
||||
x2 = x4;
|
||||
x3 = x4;
|
||||
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
}
|
||||
|
||||
// string mapping over non-string pattern literals is preserved
|
||||
|
||||
type NonStringPat = Uppercase<`aA${number}${bigint}${boolean}`>;
|
||||
type EquivalentNonStringPat = `AA${Uppercase<`${number}`>}${Uppercase<`${bigint}`>}${Uppercase<`${boolean}`>}`;
|
||||
|
||||
function f4(x1: NonStringPat, x2: EquivalentNonStringPat) {
|
||||
// Should both work
|
||||
x1 = x2;
|
||||
x2 = x1;
|
||||
}
|
||||
|
||||
// Capitalize and uncapitalize on template literals
|
||||
|
||||
function f5(
|
||||
cap_tem: `A${string}`,
|
||||
cap_str: Capitalize<string>,
|
||||
cap_tem_map: Capitalize<`A${string}`>,
|
||||
cap_tem_map2: Capitalize<`a${string}`>,
|
||||
uncap_tem: `a${string}`,
|
||||
uncap_str: Uncapitalize<string>,
|
||||
uncap_tem_map: Uncapitalize<`A${string}`>,
|
||||
uncap_tem_map2: Uncapitalize<`a${string}`>,
|
||||
) {
|
||||
// All these are capitalized
|
||||
cap_str = cap_tem;
|
||||
cap_str = cap_tem_map;
|
||||
cap_str = cap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
cap_tem = cap_tem_map;
|
||||
cap_tem = cap_tem_map2;
|
||||
cap_tem_map = cap_tem_map2;
|
||||
cap_tem_map = cap_tem;
|
||||
cap_tem_map2 = cap_tem_map;
|
||||
cap_tem_map2 = cap_tem;
|
||||
|
||||
// meanwhile, these all require a `A` prefix
|
||||
cap_tem = cap_str;
|
||||
cap_tem_map = cap_str;
|
||||
cap_tem_map2 = cap_str;
|
||||
|
||||
// All these are uncapitalized
|
||||
uncap_str = uncap_tem;
|
||||
uncap_str = uncap_tem_map;
|
||||
uncap_str = uncap_tem_map2;
|
||||
|
||||
// these are all equivalent
|
||||
uncap_tem = uncap_tem_map;
|
||||
uncap_tem = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem_map2;
|
||||
uncap_tem_map = uncap_tem;
|
||||
uncap_tem_map2 = uncap_tem_map;
|
||||
uncap_tem_map2 = uncap_tem;
|
||||
|
||||
// meanwhile, these all require a `a` prefix
|
||||
uncap_tem = uncap_str;
|
||||
uncap_tem_map = uncap_str;
|
||||
uncap_tem_map2 = uncap_str;
|
||||
}
|
||||
@ -3,29 +3,29 @@
|
||||
|
||||
type TU1 = Uppercase<'hello'>; // "HELLO"
|
||||
type TU2 = Uppercase<'foo' | 'bar'>; // "FOO" | "BAR"
|
||||
type TU3 = Uppercase<string>; // string
|
||||
type TU4 = Uppercase<any>; // any
|
||||
type TU3 = Uppercase<string>; // Uppercase<string>
|
||||
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
|
||||
type TU5 = Uppercase<never>; // never
|
||||
type TU6 = Uppercase<42>; // Error
|
||||
|
||||
type TL1 = Lowercase<'HELLO'>; // "hello"
|
||||
type TL2 = Lowercase<'FOO' | 'BAR'>; // "foo" | "bar"
|
||||
type TL3 = Lowercase<string>; // string
|
||||
type TL4 = Lowercase<any>; // any
|
||||
type TL3 = Lowercase<string>; // Lowercase<string>
|
||||
type TL4 = Lowercase<any>; // Lowercase<`${any}`>
|
||||
type TL5 = Lowercase<never>; // never
|
||||
type TL6 = Lowercase<42>; // Error
|
||||
|
||||
type TC1 = Capitalize<'hello'>; // "Hello"
|
||||
type TC2 = Capitalize<'foo' | 'bar'>; // "Foo" | "Bar"
|
||||
type TC3 = Capitalize<string>; // string
|
||||
type TC4 = Capitalize<any>; // any
|
||||
type TC3 = Capitalize<string>; // Capitalize<string>
|
||||
type TC4 = Capitalize<any>; // Capitalize<`${any}`>
|
||||
type TC5 = Capitalize<never>; // never
|
||||
type TC6 = Capitalize<42>; // Error
|
||||
|
||||
type TN1 = Uncapitalize<'Hello'>; // "hello"
|
||||
type TN2 = Uncapitalize<'Foo' | 'Bar'>; // "foo" | "bar"
|
||||
type TN3 = Uncapitalize<string>; // string
|
||||
type TN4 = Uncapitalize<any>; // any
|
||||
type TN3 = Uncapitalize<string>; // Uncapitalize<string>
|
||||
type TN4 = Uncapitalize<any>; // Uncapitalize<`${any}`>
|
||||
type TN5 = Uncapitalize<never>; // never
|
||||
type TN6 = Uncapitalize<42>; // Error
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user