mirror of
https://github.com/nushell/nushell.git
synced 2025-08-12 22:47:57 +02:00
allow records to have type annotations (#8914)
# Description follow up to #8529 cleaned up version of #8892 - the original syntax is okay ```nu def okay [rec: record] {} ``` - you can now add type annotations for fields if you know them before hand ```nu def okay [rec: record<name: string>] {} ``` - you can specify multiple fields ```nu def okay [person: record<name: string age: int>] {} # an optional comma is allowed def okay [person: record<name: string, age: int>] {} ``` - if annotations are specified, any use of the command will be type checked against the specified type ```nu def unwrap [result: record<ok: bool, value: any>] {} unwrap {ok: 2, value: "value"} # errors with Error: nu::parser::type_mismatch × Type mismatch. ╭─[entry #4:1:1] 1 │ unwrap {ok: 2, value: "value"} · ───────┬───── · ╰── expected record<ok: bool, value: any>, found record<ok: int, value: string> ╰──── ``` > here the error is in the `ok` field, since `any` is coerced into any type > as a result `unwrap {ok: true, value: "value"}` is okay - the key must be a string, either quoted or unquoted ```nu def err [rec: record<{}: list>] {} # errors with Error: × `record` type annotations key not string ╭─[entry #7:1:1] 1 │ def unwrap [result: record<{}: bool, value: any>] {} · ─┬ · ╰── must be a string ╰──── ``` - a key doesn't have to have a type in which case it is assumed to be `any` ```nu def okay [person: record<name age>] {} def okay [person: record<name: string age>] {} ``` - however, if you put a colon, you have to specify a type ```nu def err [person: record<name: >] {} # errors with Error: nu::parser::parse_mismatch × Parse mismatch during operation. ╭─[entry #12:1:1] 1 │ def unwrap [res: record<name: >] { $res } · ┬ · ╰── expected type after colon ╰──── ``` # User-Facing Changes **[BREAKING CHANGES]** - this change adds a field to `SyntaxShape::Record` so any plugins that used it will have to update and include the field. though if you are unsure of the type the record expects, `SyntaxShape::Record(vec![])` will suffice
This commit is contained in:
@ -95,7 +95,7 @@ pub enum SyntaxShape {
|
||||
Range,
|
||||
|
||||
/// A record value, eg `{x: 1, y: 2}`
|
||||
Record,
|
||||
Record(Vec<(String, SyntaxShape)>),
|
||||
|
||||
/// A math expression which expands shorthand forms on the lefthand side, eg `foo > 1`
|
||||
/// The shorthand allows us to more easily reach columns inside of the row being passed in
|
||||
@ -151,7 +151,13 @@ impl SyntaxShape {
|
||||
SyntaxShape::OneOf(_) => Type::Any,
|
||||
SyntaxShape::Operator => Type::Any,
|
||||
SyntaxShape::Range => Type::Any,
|
||||
SyntaxShape::Record => Type::Record(vec![]), // FIXME: What role should fields play in the Record type?
|
||||
SyntaxShape::Record(entries) => {
|
||||
let ty = entries
|
||||
.iter()
|
||||
.map(|(key, val)| (key.clone(), val.to_type()))
|
||||
.collect();
|
||||
Type::Record(ty)
|
||||
}
|
||||
SyntaxShape::RowCondition => Type::Bool,
|
||||
SyntaxShape::Boolean => Type::Bool,
|
||||
SyntaxShape::Signature => Type::Signature,
|
||||
@ -194,7 +200,21 @@ impl Display for SyntaxShape {
|
||||
SyntaxShape::Binary => write!(f, "binary"),
|
||||
SyntaxShape::Table => write!(f, "table"),
|
||||
SyntaxShape::List(x) => write!(f, "list<{x}>"),
|
||||
SyntaxShape::Record => write!(f, "record"),
|
||||
SyntaxShape::Record(entries) => {
|
||||
if entries.is_empty() {
|
||||
write!(f, "record")
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"record<{}>",
|
||||
entries
|
||||
.iter()
|
||||
.map(|(x, y)| format!("{x}: {y}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
SyntaxShape::Filesize => write!(f, "filesize"),
|
||||
SyntaxShape::Duration => write!(f, "duration"),
|
||||
SyntaxShape::DateTime => write!(f, "datetime"),
|
||||
|
Reference in New Issue
Block a user