slint-ui/slint · error

Unmapped struct field type

Error message

Unmapped struct field type `{other}` in for_each_builtin_structs!. Extend `map_field_type` in api/node/build.rs.

What it means

map_field_type is the build-script type map that translates Rust field types of builtin structs (via for_each_builtin_structs!) into TypeScript types for the generated language module. This panic is a deliberate forward-compatibility guard: a newly added builtin struct field has a Rust type not present in the match, and the build fails loudly instead of silently emitting 'unknown' in the generated .d.ts. The input at fault is the unmapped type string.

Solutions

  1. Add a match arm in map_field_type in api/node/build.rs mapping the new Rust type to its TypeScript equivalent
  2. If the type is not representable in TS, map it to 'unknown' or 'any' deliberately and document why
  3. Check whether the field should be skipped from generation instead of typed (adjust the struct filtering upstream)
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at api/node/build.rs:211 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/4732ca41031ebf71. Report an issue: GitHub.

Appendix: source

Thrown at api/node/build.rs:211

    ts.push_str("}\n");

    write_if_changed(&generated_dir().join("language.ts"), &ts);
}

/// Map a Rust field type (as stringified by the macro) to the TS type used in the generated
/// language module. Fails the build with a clear message when a new struct adds an unmapped
/// type — better than silently emitting `unknown`.
fn map_field_type(rust_ty: &str, in_language: &HashSet<&'static str>) -> String {
    let t = rust_ty.trim();
    match t {
        "bool" => "boolean".to_string(),
        "i32" | "f32" | "f64" | "Coord" => "number".to_string(),
        "SharedString" => "string".to_string(),
        // Types exposed by the binding outside the `language` namespace.
        "DataTransfer" => "DataTransfer".to_string(),
        "LogicalPosition" => "{ x: number; y: number }".to_string(),
        ident if in_language.contains(ident) => ident.to_string(),
        other => panic!(
            "Unmapped struct field type `{other}` in for_each_builtin_structs!. \
             Extend `map_field_type` in api/node/build.rs."
        ),
    }
}

/// Compute the JS default expression for a struct field of the given Rust type.
/// A default value declared in builtin_structs.rs wins; otherwise primitives
/// fall back to zero/empty/false, enum fields use the first-variant kebab string (matching
/// the Rust `Default` impl), and nested struct fields recurse via `_data.<Name>()`.
fn field_default(
    rust_ty: &str,
    declared: Option<&str>,
    enum_defaults: &HashMap<&'static str, String>,
    structs: &HashSet<&'static str>,
) -> String {
    if let Some(declared) = declared {
        let text: String =

View on GitHub (pinned to bb937076de)