flutterdartinheritanceabstraction

How to extend ThemeData and override a property type


I am using ThemeData's "extensions" property:

ThemeData(
...
  extensions: <ThemeExtension>[
    CustomThemeExtension(
    ...
    ),
  ...
),

by looking at its definition: Iterable<ThemeExtension<dynamic>>? extensions,

which makes sense, but forces me to null check each and every use:

Text(
  carouselModel.title,
  style: themeState
    .extension<CustomTextTheme>()
    ?.h1Bold
    .copyWith(
      color: themeState
      .extension<CustomThemeExtension>()
      ?.primaryBrand,
    ),
    textAlign: TextAlign.center,
),

Is there a way to change the definition to be null safe, and get rid of all those ??

Because ThemeData is part of the framework, is immutable, and has a factory constructor, something like this will not work.

If I had control over ThemeData, I could do something like this, but nope.

I have tried extending ThemeData and @override extensions, but to no avail.

Any help will be much appreciated.


Solution

  • You can use extension on ThemeData:

    extension ThemeDataExt on ThemeData {
       ThemeExtension get ext => extension<ThemeExtension>()!;
    }
    

    Then you can use it like this:

    Text(
      carouselModel.title,
      style: themeState.ext.h1Bold
        .copyWith(
          color: themeState.ext.primaryBrand,
        ),
        textAlign: TextAlign.center,
    ),
    

    The ! operator casts the extension to be non-nullable, it can throw a runtime exception if the cast fails. You can maybe replace it by a ?? ThemeExtension() to use default values of your theme extension.