ObjectType substituteGenerics(Map<String, JSType> concreteTypes) { if (concreteTypes.isEmpty()) { return this; } PersistentMap<String, Property> newProps = PersistentMap.create(); for (Map.Entry<String, Property> propsEntry : this.props.entrySet()) { String pname = propsEntry.getKey(); Property newProp = propsEntry.getValue().substituteGenerics(concreteTypes); newProps = newProps.with(pname, newProp); } FunctionType newFn = fn == null ? null : fn.substituteGenerics(concreteTypes); return makeObjectType( nominalType == null ? null : nominalType.instantiateGenerics(concreteTypes), newProps, newFn, newFn != null && newFn.isQmarkFunction() || isLoose, objectKind); }