Repository: astral-sh/ruff
File: crates/ty_python_semantic/src/types/diagnostic.rs (Rust)

Code before:
                            "union"
                        } else {
                            "intersection"
                        },
                        full_object_ty = full_object_ty.display(db)
                    ))
                } else {
                    context
                        .secondary(typed_dict_node)
                        .message(format_args!("TypedDict `{typed_dict_name}`"))
                });

                let existing_keys = items.iter().map(|(name, _)| name.as_str());

                diagnostic.set_primary_message(format!(
                    "Unknown key \"{key}\"{hint}",
                    hint = if let Some(suggestion) = did_you_mean(existing_keys, key) {
                        format!(" - did you mean \"{suggestion}\"?")
                    } else {
                        String::new()
                    }
                ));
            }
            _ => {
                let mut diagnostic = builder.into_diagnostic(format_args!(
                    "Invalid key of type `{}` for TypedDict `{}`",
                    key_ty.display(db),
                    typed_dict_ty.display(db),
                ));

                if let Some(full_object_ty) = full_object_ty {
                    diagnostic.info(format_args!(
                        "The full type of the subscripted object is `{}`",
                        full_object_ty.display(db)
                    ));
                }
            }
        }
    }
}

pub(super) fn report_namedtuple_field_without_default_after_field_with_default<'db>(
    context: &InferContext<'db, '_>,
    class: ClassLiteral<'db>,
    (field, field_def): &(Name, Option<Definition<'db>>),
    (field_with_default, field_with_default_def): &(Name, Option<Definition<'db>>),
) {
    let db = context.db();
    let module = context.module();

    let diagnostic_range = field_def

Review comment (suggestion):
for consistency with the other message, which now uses the phrase "a string literal key" rather than "string literal keys"

```suggestion
                    "TypedDict `{}` can only be subscripted with a string literal key, \
```

Code after:
                            "union"
                        } else {
                            "intersection"
                        },
                        full_object_ty = full_object_ty.display(db)
                    ))
                } else {
                    context
                        .secondary(typed_dict_node)
                        .message(format_args!("TypedDict `{typed_dict_name}`"))
                });

                let existing_keys = items.iter().map(|(name, _)| name.as_str());

                diagnostic.set_primary_message(format!(
                    "Unknown key \"{key}\"{hint}",
                    hint = if let Some(suggestion) = did_you_mean(existing_keys, key) {
                        format!(" - did you mean \"{suggestion}\"?")
                    } else {
                        String::new()
                    }
                ));
            }
            _ => {
                let mut diagnostic = builder.into_diagnostic(format_args!(
                    "TypedDict `{}` can only be subscripted with string literal keys, \
                     got key of type `{}`",
                    typed_dict_ty.display(db),
                    key_ty.display(db),
                ));

                if let Some(full_object_ty) = full_object_ty {
                    diagnostic.info(format_args!(
                        "The full type of the subscripted object is `{}`",
                        full_object_ty.display(db)
                    ));
                }
            }
        }
    }
}

pub(super) fn report_namedtuple_field_without_default_after_field_with_default<'db>(
    context: &InferContext<'db, '_>,
    class: ClassLiteral<'db>,
    (field, field_def): &(Name, Option<Definition<'db>>),
    (field_with_default, field_with_default_def): &(Name, Option<Definition<'db>>),
) {
    let db = context.db();
    let module = context.module();