diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04e0341f..f499a38d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Next
+- Fixed: Crash with `funcsMap[propKey] is not a function` when the theme has no `textVariants` or a variant contains props that are not Restyle props.
- Chore: Use npm trusted publishing and isolate package builds from publishing permissions.
## 2.4.5 - 2025-03-19
diff --git a/src/composeRestyleFunctions.ts b/src/composeRestyleFunctions.ts
index a598c259..f40f6a7b 100644
--- a/src/composeRestyleFunctions.ts
+++ b/src/composeRestyleFunctions.ts
@@ -54,7 +54,9 @@ const composeRestyleFunctions = <
// We make the assumption that the props object won't have extra prototype keys.
// eslint-disable-next-line guard-for-in
for (const key in props) {
- const mappedProps = funcsMap[key](props, options);
+ const func = funcsMap[key];
+ if (func === undefined) continue;
+ const mappedProps = func(props, options);
// eslint-disable-next-line guard-for-in
for (const mappedKey in mappedProps) {
styles[mappedKey as keyof ViewStyle] = mappedProps[mappedKey];
diff --git a/src/test/createText.test.tsx b/src/test/createText.test.tsx
index 364834c9..eba3f7cd 100644
--- a/src/test/createText.test.tsx
+++ b/src/test/createText.test.tsx
@@ -96,6 +96,47 @@ describe('createText', () => {
]);
});
+ it('ignores textVariant values that are not restyle props', () => {
+ const themeWithNonRestyleProp = createTheme({
+ ...theme,
+ textVariants: {
+ ...theme.textVariants,
+ title: {
+ ...theme.textVariants.title,
+ transform: [{rotate: '45deg'}],
+ },
+ },
+ });
+
+ const {root} = render(
+
+ Some text
+ ,
+ );
+
+ expect(root.findByType(RNText).props.style).toStrictEqual([
+ {
+ color: palette.black,
+ fontSize: 48,
+ fontWeight: 'bold',
+ },
+ ]);
+ });
+
+ it('renders when the theme has no textVariants', () => {
+ const {textVariants, ...themeWithoutTextVariants} = theme;
+
+ const {root} = render(
+
+ Some text
+ ,
+ );
+
+ expect(root.findByType(RNText).props.style).toStrictEqual([
+ {color: palette.black},
+ ]);
+ });
+
it('passes all React Native Text Style Props', () => {
const {root} = render(
diff --git a/src/test/createVariant.test.ts b/src/test/createVariant.test.ts
index 9dc1803c..9ddf2e2f 100644
--- a/src/test/createVariant.test.ts
+++ b/src/test/createVariant.test.ts
@@ -175,6 +175,28 @@ describe('createVariant', () => {
expect(variant.func({}, {theme, dimensions})).toStrictEqual({});
});
+ it('ignores variant values that are not restyle props', () => {
+ const themeWithNonRestyleProp = {
+ ...theme,
+ textVariants: {
+ ...theme.textVariants,
+ rotated: {
+ fontSize: 14,
+ transform: [{rotate: '45deg'}],
+ },
+ },
+ };
+ const variant = createVariant({themeKey: 'textVariants'});
+ expect(
+ variant.func(
+ {variant: 'rotated'},
+ {theme: themeWithNonRestyleProp, dimensions},
+ ),
+ ).toStrictEqual({
+ fontSize: 14,
+ });
+ });
+
it('supports referencing other theme values in the variant', () => {
const variant = createVariant({themeKey: 'textVariants'});
expect(