本页还没有译文
本页 27 段还没译成简体中文,下面显示的是英文原文。TypeScript
还没翻译译自英文(tanstack.com)本页 27 段都还没译
TanStack Charts is designed so ordinary chart code names its application types once. Data, channel outputs, scale domains, focus points, and framework props then infer from the definition.
Infer from mark channels
import { scaleTime } from 'd3-scale'
import { defineChart, lineY } from '@tanstack/charts'
import { scaleLinear } from '@tanstack/charts/scales/linear'
interface Reading {
id: string
recordedAt: Date
temperature: number
}
const readings: readonly Reading[] = []
const definition = defineChart({
marks: [
lineY(readings, {
x: 'recordedAt',
y: 'temperature',
}),
],
scales: {
x: { scale: scaleTime },
y: { scale: scaleLinear },
},
})Here the datum is Reading, x values are Date, and y values are number.
An incompatible scale or channel field fails at the definition instead of
surfacing later in a tooltip callback.
Capture application values
function createTrafficDefinition(rows: readonly Reading[]) {
return defineChart({
marks: [
lineY(rows, {
x: 'recordedAt',
y: 'temperature',
}),
],
scales: {
x: { scale: scaleTime },
y: { scale: scaleLinear },
},
})
}Framework components should memoize the complete definition:
const definition = useMemo(() => createTrafficDefinition(readings), [readings])
return <Chart definition={definition} ariaLabel="Temperature history" />Definition identity tells the host when captured application data or options changed. A responsive definition callback still rebuilds when the host size changes:
function createTrafficDefinition(rows: readonly Reading[]) {
return defineChart(({ width }) => ({
marks: [
lineY(rows, {
x: 'recordedAt',
y: 'temperature',
}),
],
scales: {
x: { scale: scaleTime },
y: { scale: scaleLinear },
},
margin: width < 480 ? 24 : 40,
}))
}Keep literal information
Prefer:
- field-name channels such as
x: 'recordedAt'; - typed accessors when a value is derived;
defineChart({...})or a responsivedefineChart(() => ({...}));satisfieswhen naming a configuration object separately.
Avoid annotating an intermediate object as broad ChartSpec before passing it
to defineChart. That discards the literal mark tuple used for axis and
callback inference.
The mark tuple determines the value type accepted by each reserved positional
scale. scales.x and scales.y are always present in canonical definitions.
Use null for a dimension that no mark materializes. Named scale selectors on
marks keep those values out of the reserved entry's inferred type.
Callback types
Focus and selection callbacks receive the original datum and inferred coordinate types:
<Chart
definition={definition}
ariaLabel="Temperature readings"
onSelect={(point) => {
if (!point) return
point.datum.recordedAt // Date
point.xValue // Date
point.yValue // number
}}
/>Do not cast a callback parameter or re-find its datum by key. If inference has
degraded to unknown, move back to the definition and look for an erased mark
tuple, an any annotation, or an untyped custom scale.
Extract inferred types
The public type utilities are useful at extension boundaries:
import type {
ChartMarkDatum,
ChartSpecDatum,
ChartSpecXValue,
ChartSpecYValue,
} from '@tanstack/charts'
import type {
ChartMarkPointX,
ChartMarkPointY,
} from '@tanstack/charts/mark/scale-values'Use them to describe reusable helpers without repeating a datum or coordinate union manually. The exact utility contracts are listed in Types.
Custom marks
createMark<TDatum, TXValue, TYValue, TXScaleId, TYScaleId> keeps interaction
points and scale values aligned for the common case. The scale ID parameters
default to x and y. Provide them when a custom mark selects named scales so
its values do not widen the reserved scale types. Use the advanced scale-value
factory when the materialized axis domain differs from the point anchor or
when a custom mark is positionless and declares both scale value types as
never.
See Custom Marks and Renderers. A custom
extension that requires as unknown as, a private import, or suppressed type
errors indicates a missing public boundary and should be reduced to a failing
type test.
Type tests
Keep positive and negative examples near reusable definitions:
// @ts-expect-error chart options do not accept formal input
mountChart(container, {
definition,
input: { rows: readings },
ariaLabel: 'Readings',
})Use @ts-expect-error only when the test asserts a specific rejected contract.
Do not use it to make application examples compile.
No-cast checklist
- Datum and captured application values are typed at the application boundary.
- Channel fields are checked against the datum.
- Scale domains match inferred coordinate types.
- Definitions preserve their literal mark tuple.
- Adapters infer props from the definition.
- Callbacks receive original typed data.
- Custom extensions expose, rather than erase, their generic relationship.