# isTypeMatch method

1. @override

Future<bool> isTypeMatch(

1. String name,
2. Class typeToMatch, [
3. bool allowPodProviderInit = false

])
override

Checks if the pod with the specified name matches the given type.

This method is useful for checking the type of a pod before attempting to retrieve it.

## Usage Example:

    if (await factory.isTypeMatch('userService', Class<UserService>())) {
      final userService = await factory.getPod<UserService>('userService');
      userService.doSomething();
    }

@param name The name of the pod to check @param typeToMatch The class type to match @return A Future that completes with true if the pod matches the type

## Implementation

    @override
    Future<bool> isTypeMatch(String name, Class typeToMatch, [bool allowPodProviderInit = false]) async {
      final transformed = transformedPodName(name);
      final isFactoryDereference = PodUtils.isFactoryDereference(name);

      // 1) check local singleton cache first (fast path)
      final cachedHolder = await getSingletonCache(transformed, false);
      if (cachedHolder != null && cachedHolder.getType()?.getType() != NullablePod.CLASS.getType()) {
        final instance = cachedHolder.getValue();

        // 1.a) Instance is a PodProvider (lazy provider)
        if (instance is PodProvider) {
          // If caller asked for factory dereference (& name used factory deref), we should not treat provider as target instance.
          if (isFactoryDereference) {
            return false;
          }

          // If provider directly supports the target type, success.
          if (instance.supportsType(typeToMatch)) {
            return true;
          }

          // Try to determine what the provider would produce (may initialize provider depending on flag).
          final providedClass = await getPodProviderType(instance, allowPodProviderInit);
          if (providedClass == null) {
            // Can't determine the provided type => no match.
            return false;
          }

          // If target type is assignable from the provider's produced type => match.
          if (typeToMatch.isAssignableFrom(providedClass)) {
            return true;
          }

          // If target has generics, consult local merged definition for componentType heuristics.
          if (typeToMatch.hasGenerics() && containsDefinition(transformed)) {
            final merged = getLocalMergedPodDefinition(transformed);
            final Class targetClass = merged.type;

            // If merged type itself is a PodProvider subclass, inspect component type
            if (POD_PROVIDER_CLASS.isAssignableFrom(targetClass)) {
              // Avoid confusing provider types: if requested type is not a provider itself
              // but could match the provider's component type, return that result.
              if (!POD_PROVIDER_CLASS.isAssignableFrom(typeToMatch) && !typeToMatch.isAssignableFrom(targetClass)) {
                final comp = targetClass.componentType();
                return comp != null && typeToMatch.isAssignableFrom(comp);
              }
            } else {
              // Otherwise compare typeToMatch with the merged targetClass
              return typeToMatch.isAssignableFrom(targetClass);
            }
          }

          // No match from provider path
          return false;
        }

        // 1.b) Instance is not a provider
        if (isFactoryDereference) {
          // Caller explicitly asked for factory reference (e.g. "&podName") but the cached instance is the pod itself,
          // so the factory reference semantics don't match.
          return false;
        }

        // Direct instance check
        if (typeToMatch.isInstance(instance)) {
          return true;
        }

        // If target type has generics, consult local merged definition metadata as fallback
        if (typeToMatch.hasGenerics() && containsDefinition(transformed)) {
          final definition = getLocalMergedPodDefinition(transformed);
          final Class targetType = definition.type;

          if (!targetType.isInstance(instance)) {
            final Class? componentToMatch = typeToMatch.componentType();
            if (componentToMatch != null && !componentToMatch.isInstance(instance)) {
              return false;
            }
            if (typeToMatch.isAssignableFrom(targetType)) {
              return true;
            }
          }
          return typeToMatch.isAssignableFrom(targetType);
        }

        // No match against cached instance
        return false;
      } // end cachedHolder != null

      // 2) No cached instance -> check local definition metadata (if any)
      if (containsDefinition(transformed)) {
        final def = getLocalMergedPodDefinition(transformed);
        final Class declaredType = def.type;

        // If caller asked for factory deref, we only match if declaredType is PodProvider (or subclass)
        if (isFactoryDereference) {
          return POD_PROVIDER_CLASS.isAssignableFrom(declaredType);
        }

        // Direct assignability from declared type is a match
        if (typeToMatch.isAssignableFrom(declaredType)) {
          return true;
        }

        // If typeToMatch has generics, try matching component/generic types of declaredType
        if (typeToMatch.hasGenerics()) {
          final Class? declaredComponent = declaredType.componentType();
          final Class? wantedComponent = typeToMatch.componentType();
          if (wantedComponent != null && declaredComponent != null) {
            if (wantedComponent.isAssignableFrom(declaredComponent)) {
              return true;
            }
          }
        }

        // If declaredType is a PodProvider, check the provider's produced type (without instantiating provider unless allowed)
        if (POD_PROVIDER_CLASS.isAssignableFrom(declaredType)) {
          // If we can determine produced type from the definition metadata, prefer that.
          final Class? declaredProvided = def.type;
          if (declaredProvided != null) {
            return typeToMatch.isAssignableFrom(declaredProvided);
          }

          // If no metadata available and we are allowed to init provider, try instantiating provider to inspect
          if (allowPodProviderInit) {
            try {
              final providerInstance = await getPod(transformed, []);
              if (providerInstance is PodProvider) {
                final produced = await getPodProviderType(providerInstance, true);
                if (produced != null && typeToMatch.isAssignableFrom(produced)) {
                  return true;
                }
              }
            } catch (_) {
              // ignore; fall through to parent check
            }
          }
        }

        // Not matched by local definition
      }

      // 3) Nothing local matched -> delegate to parent factory (if any)
      final parent = getParentFactory();
      if (parent != null) {
        try {
          // Assume parent exposes the same isTypeMatch API and is async
          return await parent.isTypeMatch(name, typeToMatch, allowPodProviderInit);
        } catch (_) {
          // swallow and return false for robust fallback semantics
          return false;
        }
      }

      // 4) No parent and no match -> false
      return false;
    }