1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
//! This module defines structs used to create static descriptions of TypeScript
//! type definitions.
/// A description of the type information required to produce a TypeScript type
/// definition.
#[derive(Debug, Clone, Copy)]
pub enum TypeInfo {
/// This info describes a "native" TypeScript type which does not require a
/// type definition.
Native(NativeTypeInfo),
/// This info describes a "defined" TypeScript type which does require a
/// type definition.
Defined(DefinedTypeInfo),
}
/// Type information describing a "native" TypeScript type.
///
/// Native types have a definition which only uses built-in or pre-defined
/// TypeScript types. Therefore a definition for them is not emitted, and they
/// are referenced by their definition.
#[derive(Debug, Clone, Copy)]
pub struct NativeTypeInfo {
/// A type expression describing this native type.
pub r#ref: TypeExpr,
}
/// Type information describing a "defined" TypeScript type.
///
/// Defined types need to have a type definition emitted in the TypeScript
/// module. They are referenced using their name.
#[derive(Debug, Clone, Copy)]
pub struct DefinedTypeInfo {
/// The definition of this type.
///
/// # Implementation Note
/// The body of the definition **must** be *invariant* of the Rust
/// type's generic parameters. In other words, if the Rust type is generic,
/// its definition must be the same for any value of its generic
/// parameters. Where the definition needs to reference generic parameters,
/// you must instead use a placeholder type whose
/// [`INFO`](crate::emit::TypeDef::INFO) is [`TypeInfo::Native`] and the
/// native type reference is a [`TypeExpr::Name`] referencing the generic
/// parameter.
pub def: TypeDefinition,
/// The specific values of the generic arguments of this type for this
/// instance of the generic type.
///
/// This list should contain references to the type info of each type
/// parameter of this Rust type. Unlike `def`, these values **should**
/// depend on the generic parameters of this type.
pub generic_args: List<TypeExpr>,
}
/// The TypeScript definition of a type.
#[derive(Debug, Clone, Copy)]
pub struct TypeDefinition {
/// The documentation for this type definition.
pub docs: Option<Docs>,
/// The namespace path for this type.
pub path: List<Ident>,
/// The name of this type.
pub name: Ident,
/// The generic variables for this type defintion.
///
/// If empty, the type does not have generics.
pub generic_vars: List<Ident>,
/// The definition of this type.
pub def: TypeExpr,
}
/// A TypeScript type expression.
///
/// This type is not intended to cover _all_ possible TypeScript type syntax,
/// only that which is needed by the types defined in this crate and as produced
/// by [`#[derive(TypeDef)]`](macro@crate::TypeDef).
#[derive(Debug, Clone, Copy)]
pub enum TypeExpr {
/// A reference to another type.
Ref(&'static TypeInfo),
/// A reference to a bare type name which should already be defined.
Name(TypeName),
/// A type-level string literal.
String(TypeString),
/// A tuple type.
Tuple(TypeTuple),
/// An object type.
Object(TypeObject),
/// An array type.
Array(TypeArray),
/// A union type.
Union(TypeUnion),
/// An intersection type.
Intersection(TypeIntersection),
}
/// A reference to a built-in TypeScript type, analogous to a Rust path with
/// optional generics.
#[derive(Debug, Clone, Copy)]
pub struct TypeName {
/// The namespace path for this type.
pub path: List<Ident>,
/// The name of this type.
pub name: Ident,
/// The generic arguments for this type.
///
/// If empty, the type does not have generics.
pub generic_args: List<TypeExpr>,
}
/// A TypeScript type-level string literal.
#[derive(Debug, Clone, Copy)]
pub struct TypeString {
/// The documentation for this type string.
pub docs: Option<Docs>,
/// The value of this literal.
pub value: &'static str,
}
/// A TypeScript tuple type.
///
/// In TypeScript, tuples are represented as constant-length arrays where each
/// element can have a distinct type. Values of these types are encoded as
/// arrays in JSON, which are expected to have a constant length.
#[derive(Debug, Clone, Copy)]
pub struct TypeTuple {
/// The documentation for this tuple.
pub docs: Option<Docs>,
/// The types of the elements of this tuple.
///
/// If the elements are empty, the only valid value for this type is the
/// empty array `[]`.
pub elements: List<TypeExpr>,
}
/// A TypeScript object type.
#[derive(Debug, Clone, Copy)]
pub struct TypeObject {
/// The documentation for this object.
pub docs: Option<Docs>,
/// The fields of this object.
pub fields: List<ObjectField>,
}
/// A field of a TypeScript object type.
#[derive(Debug, Clone, Copy)]
pub struct ObjectField {
/// The documentation for this field.
pub docs: Option<Docs>,
/// The name of this field.
pub name: TypeString,
/// Whether this field is optional or not.
///
/// This corresponds with the `?` suffix on the field name which makes it
/// valid to omit the field entirely from the object, effectively giving it
/// a value of `undefined`. In JSON, omitted optional fields are omitted
/// from the object serialization.
pub optional: bool,
/// The type of this field.
pub r#type: TypeExpr,
}
/// A TypeScript array type.
///
/// In TypeScript, an array is distinct from a tuple by the fact that it may
/// have any length and every element has the same type (although that type may
/// be a union so the elements may have different runtime types). Values of both
/// of these types are encoded as arrays in JSON.
#[derive(Debug, Clone, Copy)]
pub struct TypeArray {
/// The documentation for this array.
pub docs: Option<Docs>,
/// The type of items of this array.
pub item: &'static TypeExpr,
}
/// A TypeScript union type.
#[derive(Debug, Clone, Copy)]
pub struct TypeUnion {
/// The documentation for this union.
pub docs: Option<Docs>,
/// The types that comprise this union.
///
/// If the members are empty, this type describes the vacuous union type
/// which is equivalent to `never`. If the members contain only one type,
/// this type is equivalent to that type.
pub members: List<TypeExpr>,
}
/// A TypeScript intersection type.
///
/// Note that not all valid TypeScript intersection types are possible to
/// represent using JSON. In general, only object types with disjoint fields can
/// be intersected and still be accurately encoded as JSON (the resulting type
/// being an object with the combined fields of all the intersection members).
#[derive(Debug, Clone, Copy)]
pub struct TypeIntersection {
/// The documentation for this intersection.
pub docs: Option<Docs>,
/// The types that comprise this intersection.
///
/// If the members are empty, this type describes the vacuous intersection
/// type which is equivalent to `any`. If the members contain only one
/// type, this type is equivalent to that type.
pub members: List<TypeExpr>,
}
/// A TypeScript identifier.
///
/// Note that TypeScript's rules for valid identifiers are not checked by this
/// library. It is the user's responsibility to ensure that all identifiers are
/// valid in TypeScript in order for the resulting TypeScript module to be
/// valid.
#[derive(Debug, Clone, Copy)]
pub struct Ident(pub &'static str);
/// A documentation string.
///
/// The string value should be the plain unformatted documentation without any
/// `/**` or indentation in it. Lines may be separate by newlines.
#[derive(Debug, Clone, Copy)]
pub struct Docs(pub &'static str);
/// An alias for lists used in type expressions.
pub type List<T> = &'static [T];
impl TypeExpr {
/// A helper function to create a type expression representing just an
/// identifier.
pub const fn ident(ident: Ident) -> Self {
Self::Name(TypeName::ident(ident))
}
}
impl TypeName {
/// A helper function to create a type name representing just an identifier.
pub const fn ident(ident: Ident) -> Self {
Self {
path: &[],
name: ident,
generic_args: &[],
}
}
}