{"record":{"id":"b5fd866d8dcf80f0","repo":"sveltejs/svelte","slug":"cannot-interpolate-values-of-different-type","errorCode":null,"errorMessage":"Cannot interpolate values of different type","messagePattern":"Cannot interpolate values of different type","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/svelte/src/motion/tweened.js","lineNumber":24,"sourceCode":"import { linear } from '../easing/index.js';\nimport { is_date } from './utils.js';\nimport { set, state } from '../internal/client/reactivity/sources.js';\nimport { tag } from '../internal/client/dev/tracing.js';\nimport { get, render_effect } from 'svelte/internal/client';\nimport { DEV } from 'esm-env';\n\n/**\n * @template T\n * @param {T} a\n * @param {T} b\n * @returns {(t: number) => T}\n */\nfunction get_interpolator(a, b) {\n\tif (a === b || a !== a) return () => a;\n\n\tconst type = typeof a;\n\tif (type !== typeof b || Array.isArray(a) !== Array.isArray(b)) {\n\t\tthrow new Error('Cannot interpolate values of different type');\n\t}\n\n\tif (Array.isArray(a)) {\n\t\tconst arr = /** @type {Array<any>} */ (b).map((bi, i) => {\n\t\t\treturn get_interpolator(/** @type {Array<any>} */ (a)[i], bi);\n\t\t});\n\n\t\t// @ts-ignore\n\t\treturn (t) => arr.map((fn) => fn(t));\n\t}\n\n\tif (type === 'object') {\n\t\tif (!a || !b) {\n\t\t\tthrow new Error('Object cannot be null');\n\t\t}\n\n\t\tif (is_date(a) && is_date(b)) {\n\t\t\tconst an = a.getTime();","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/sveltejs/svelte/blob/20b341f10048cf1016a2028ac7eee5595cfef6a5/packages/svelte/src/motion/tweened.js#L6-L42","documentation":"`tweened()` interpolates between current value `a` and target `b`. Its `get_interpolator` requires both ends to share the same `typeof`, and arrays must match arrays. A type mismatch (number to string, object to array) is unrecoverable, so it throws. Dates, numbers, arrays, and objects are supported; mismatched types are not.","triggerScenarios":"Calling `tweenedStore.set(newValue)` where `newValue`'s type differs from the current value — e.g. tweening from `0` to `\"100\"` (number to string), or from `[1,2]` to `{x:1}` (array to object).","commonSituations":"Unvalidated API data feeding a tweened store; loose typing where a number arrives as a string; changing the data shape between updates.","solutions":["Ensure `.set()` receives the same type as the current value.","Coerce before setting: `store.set(Number(value))`.","For intentionally different end states, reset without interpolating: `.set(value, { duration: 0 })` or `hard: true`."],"exampleFix":"// before\nconst t = tweened(0);\nt.set('100'); // number -> string -> throws\n// after\nt.set(Number('100')); // both numbers\n// or snap without interpolation\nt.set(100, { duration: 0 });","handlingStrategy":"type-guard","validationCode":"function sameTweenType(a, b) {\n\treturn typeof a === typeof b && Array.isArray(a) === Array.isArray(b);\n}\nif (!sameTweenType(current, next)) throw new Error('Tween source and target must match type');","typeGuard":"function sameTweenType(a, b) {\n\treturn typeof a === typeof b && Array.isArray(a) === Array.isArray(b);\n}","tryCatchPattern":null,"preventionTips":["Coerce tween inputs to the stored type before `.set()`.","Validate API data types before feeding tweened stores.","Use `{ duration: 0 }` or `hard: true` to reset instead of tweening incompatible types.","Keep tweened value shapes stable across updates."],"tags":["tweened","motion","interpolation","type","svelte-motion"],"backgroundTag":null,"analyzedSha":"20b341f10048cf1016a2028ac7eee5595cfef6a5","analyzedAt":"2026-08-12T23:37:30.399Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}