mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-23 01:42:07 -06:00
First attempt. Basically broken.
This commit is contained in:
parent
f06d57174d
commit
7d1a980ad2
@ -334,6 +334,7 @@ namespace ts {
|
||||
const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
|
||||
|
||||
const globals = createSymbolTable();
|
||||
const deferredInferenceCache = createMap<Type | undefined>();
|
||||
let ambientModulesCache: Symbol[] | undefined;
|
||||
/**
|
||||
* List of every ambient module with a "*" wildcard.
|
||||
@ -4867,6 +4868,9 @@ namespace ts {
|
||||
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
|
||||
return getTypeOfInstantiatedSymbol(symbol);
|
||||
}
|
||||
if (getCheckFlags(symbol) & CheckFlags.DeferredInferred) {
|
||||
return inferTargetType((symbol as DeferredTransientSymbol).propertyType, (symbol as DeferredTransientSymbol).mappedType);
|
||||
}
|
||||
if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
|
||||
return getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
}
|
||||
@ -11224,42 +11228,49 @@ namespace ts {
|
||||
* property is computed by inferring from the source property type to X for the type
|
||||
* variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for).
|
||||
*/
|
||||
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, mappedTypeStack: string[]): Type {
|
||||
const properties = getPropertiesOfType(source);
|
||||
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
if (properties.length === 0 && !indexInfo) {
|
||||
return undefined;
|
||||
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType): Type {
|
||||
const key = source.id + "," + target.id;
|
||||
if (deferredInferenceCache.has(key)) {
|
||||
return deferredInferenceCache.get(key);
|
||||
}
|
||||
const typeParameter = <TypeParameter>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const inference = createInferenceInfo(typeParameter);
|
||||
const inferences = [inference];
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
const readonlyMask = target.declaration.readonlyToken ? false : true;
|
||||
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
|
||||
const members = createSymbolTable();
|
||||
for (const prop of properties) {
|
||||
const propType = getTypeOfSymbol(prop);
|
||||
// If any property contains context sensitive functions that have been skipped, the source type
|
||||
// is incomplete and we can't infer a meaningful input type.
|
||||
if (propType.flags & TypeFlags.ContainsAnyFunctionType) {
|
||||
deferredInferenceCache.set(key, function() {
|
||||
const properties = getPropertiesOfType(source);
|
||||
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
if (properties.length === 0 && !indexInfo) {
|
||||
return undefined;
|
||||
}
|
||||
const checkFlags = readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0;
|
||||
const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags);
|
||||
inferredProp.declarations = prop.declarations;
|
||||
inferredProp.type = inferTargetType(propType);
|
||||
members.set(prop.escapedName, inferredProp);
|
||||
}
|
||||
if (indexInfo) {
|
||||
indexInfo = createIndexInfo(inferTargetType(indexInfo.type), readonlyMask && indexInfo.isReadonly);
|
||||
}
|
||||
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
|
||||
const readonlyMask = target.declaration.readonlyToken ? false : true;
|
||||
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
|
||||
const members = createSymbolTable();
|
||||
for (const prop of properties) {
|
||||
const propType = getTypeOfSymbol(prop);
|
||||
// If any property contains context sensitive functions that have been skipped, the source type
|
||||
// is incomplete and we can't infer a meaningful input type.
|
||||
if (propType.flags & TypeFlags.ContainsAnyFunctionType) {
|
||||
return undefined;
|
||||
}
|
||||
const checkFlags = CheckFlags.DeferredInferred | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0);
|
||||
const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as DeferredTransientSymbol;
|
||||
inferredProp.declarations = prop.declarations;
|
||||
inferredProp.propertyType = propType; // not sure I need this.
|
||||
inferredProp.mappedType = target;
|
||||
members.set(prop.escapedName, inferredProp);
|
||||
}
|
||||
if (indexInfo) {
|
||||
// TODO: Defer this too. BARREL OF LAUGHS RIGHT THERE
|
||||
indexInfo = createIndexInfo(inferTargetType(indexInfo.type, target), readonlyMask && indexInfo.isReadonly);
|
||||
}
|
||||
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
|
||||
}());
|
||||
}
|
||||
|
||||
function inferTargetType(sourceType: Type): Type {
|
||||
inference.candidates = undefined;
|
||||
inferTypes(inferences, sourceType, templateType, 0, mappedTypeStack);
|
||||
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : emptyObjectType;
|
||||
}
|
||||
function inferTargetType(sourceType: Type, target: MappedType): Type {
|
||||
const typeParameter = <TypeParameter>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
const inference = createInferenceInfo(typeParameter);
|
||||
inference.candidates = undefined;
|
||||
inferTypes([inference], sourceType, templateType);
|
||||
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : emptyObjectType;
|
||||
}
|
||||
|
||||
function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean) {
|
||||
@ -11275,7 +11286,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, mappedTypeStack?: string[]) {
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
|
||||
let symbolStack: Symbol[];
|
||||
let visited: Map<boolean>;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
@ -11492,13 +11503,7 @@ namespace ts {
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed) {
|
||||
const key = (source.symbol ? getSymbolId(source.symbol) + "," : "") + getSymbolId(target.symbol);
|
||||
if (contains(mappedTypeStack, key)) {
|
||||
return;
|
||||
}
|
||||
(mappedTypeStack || (mappedTypeStack = [])).push(key);
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target, mappedTypeStack);
|
||||
mappedTypeStack.pop();
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (inferredType) {
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedType;
|
||||
|
||||
@ -3217,6 +3217,7 @@ namespace ts {
|
||||
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
|
||||
Late = 1 << 10, // Late-bound symbol for a computed property with a dynamic name
|
||||
DeferredInferred = 1 << 11, // Deferred inferred property of homomorphic mapped type. It is HILARIOUS.
|
||||
Synthetic = SyntheticProperty | SyntheticMethod
|
||||
}
|
||||
|
||||
@ -3226,6 +3227,11 @@ namespace ts {
|
||||
isRestParameter?: boolean;
|
||||
}
|
||||
|
||||
export interface DeferredTransientSymbol extends TransientSymbol {
|
||||
propertyType: Type;
|
||||
mappedType: MappedType;
|
||||
}
|
||||
|
||||
export const enum InternalSymbolName {
|
||||
Call = "__call", // Call signatures
|
||||
Constructor = "__constructor", // Constructor implementations
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user