Using "sel" References
The sel
object is a special import that allows you to easily reference
components with a bit more type-safety than a string. It can also be more ergonomic
than typing out a port selector.
import { sel } from "tscircuit"
export default () => (
<board width="10mm" height="10mm">
<resistor
resistance="1k"
footprint="0402"
name="R1"
/>
<capacitor
capacitance="1000pF"
footprint="0402"
name="C1"
/>
<trace from={sel.R1.pin1} to={sel.C1.pos} />
</board>
)
The sel
can be thought of as a very large mapping of conventional strings.
Here are some sel
expressions and their corresponding string:
import { sel } from "tscircuit"
sel.R1.pin1
// ".R1 > .pin1"
sel.C1.pos
// ".C1 > .pos"
sel.net.GND
// "net.GND"
sel.U1.GPIO1
// ".U1 > .GPIO1"
Type-Safe Chip Pin References
The sel
object provides enhanced type safety when working with chips by allowing you to reference pins with proper TypeScript types. There are two advanced ways to use sel
with chips:
You can pass a chip component to sel
to get fully type-safe pin accessors:
import { MyChip } from "./my-chip"
const selectors = {
U1: sel.U1(MyChip)
}
export const MyChipWithSomeTraces = () => (
<group>
<MyChip name="U1" />
<trace from={selectors.U1.VCC} to="net.VCC" />
<trace from={selectors.U1.GND} to="net.GND" />
</group>
)
In order for type-safe selectors to work, you need to define your chip component
with a ChipProps
type, like this:
import { ChipProps } from "tscircuit"
const pinLabels = {
VCC: string
GND: string
} as const
const MyChip = (props: ChipProps<typeof pinLabels>) => (
<chip {...props} pinLabels={pinLabels} />
)
sel.U1(MyChip).VCC
is the same as sel.U1.VCC
,
however, when we pass MyChip
to sel.U1
, TypeScript will check that MyChip
has a pin called VCC
and will error if it doesn't.
import { sel } from "tscircuit"
import { MyChip } from "./my-chip"
sel.U1(MyChip).VCC
// ".U1 > .VCC"
sel.U1(MyChip).GND
// ".U1 > .GND"
// TypeScript will error on non-existent pins!
// sel.U1(MyChip).DOES_NOT_EXIST -> ERROR!
Generic Pin Selectors (no chip needed!)
You can also use TypeScript generics to define custom pin types directly:
import { sel } from "tscircuit"
// Define custom pin types using generics
const selU2 = sel.U2<"custompin1" | "custompin2">()
selU2.custompin1 // Returns ".U2 > .custompin1"
selU2.custompin2 // Returns ".U2 > .custompin2"
// TypeScript will error on non-existent pins!
// selU2.doesnotexist // TypeScript error!
So sel
is a more type-safe, conventional way of writing
port selectors.