mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-24 21:52:13 +00:00
Add skip_typescript attribute to prevent .d.ts emit (#2016)
* Add skip_typescript attribute to prevent .d.ts emit * Add guide page for typescript attribute
This commit is contained in:
parent
3f4acc453b
commit
7ffb5ed70c
@ -221,6 +221,7 @@ pub struct Function {
|
||||
pub rust_attrs: Vec<syn::Attribute>,
|
||||
pub rust_vis: syn::Visibility,
|
||||
pub r#async: bool,
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -231,6 +232,7 @@ pub struct Struct {
|
||||
pub fields: Vec<StructField>,
|
||||
pub comments: Vec<String>,
|
||||
pub is_inspectable: bool,
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -243,6 +245,7 @@ pub struct StructField {
|
||||
pub getter: Ident,
|
||||
pub setter: Ident,
|
||||
pub comments: Vec<String>,
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -252,6 +255,7 @@ pub struct Enum {
|
||||
pub variants: Vec<Variant>,
|
||||
pub comments: Vec<String>,
|
||||
pub hole: u32,
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
|
@ -206,6 +206,7 @@ fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Functi
|
||||
Function {
|
||||
arg_names,
|
||||
name: &func.name,
|
||||
generate_typescript: func.generate_typescript,
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,6 +219,7 @@ fn shared_enum<'a>(e: &'a ast::Enum, intern: &'a Interner) -> Enum<'a> {
|
||||
.map(|v| shared_variant(v, intern))
|
||||
.collect(),
|
||||
comments: e.comments.iter().map(|s| &**s).collect(),
|
||||
generate_typescript: e.generate_typescript,
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,6 +309,7 @@ fn shared_struct<'a>(s: &'a ast::Struct, intern: &'a Interner) -> Struct<'a> {
|
||||
.collect(),
|
||||
comments: s.comments.iter().map(|s| &**s).collect(),
|
||||
is_inspectable: s.is_inspectable,
|
||||
generate_typescript: s.generate_typescript,
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,6 +321,7 @@ fn shared_struct_field<'a>(s: &'a ast::StructField, intern: &'a Interner) -> Str
|
||||
},
|
||||
readonly: s.readonly,
|
||||
comments: s.comments.iter().map(|s| &**s).collect(),
|
||||
generate_typescript: s.generate_typescript,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ impl<'a> Context<'a> {
|
||||
&mut self,
|
||||
export_name: &str,
|
||||
contents: &str,
|
||||
comments: Option<String>,
|
||||
comments: Option<&str>,
|
||||
) -> Result<(), Error> {
|
||||
let definition_name = generate_identifier(export_name, &mut self.defined_identifiers);
|
||||
if contents.starts_with("class") && definition_name != export_name {
|
||||
@ -119,9 +119,8 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
let contents = contents.trim();
|
||||
if let Some(ref c) = comments {
|
||||
if let Some(c) = comments {
|
||||
self.globals.push_str(c);
|
||||
self.typescript.push_str(c);
|
||||
}
|
||||
let global = match self.config.mode {
|
||||
OutputMode::Node {
|
||||
@ -804,7 +803,7 @@ impl<'a> Context<'a> {
|
||||
dst.push_str("}\n");
|
||||
ts_dst.push_str("}\n");
|
||||
|
||||
self.export(&name, &dst, Some(class.comments.clone()))?;
|
||||
self.export(&name, &dst, Some(&class.comments))?;
|
||||
self.typescript.push_str(&ts_dst);
|
||||
|
||||
Ok(())
|
||||
@ -2153,15 +2152,23 @@ impl<'a> Context<'a> {
|
||||
// on what's being exported.
|
||||
match kind {
|
||||
Kind::Export(export) => {
|
||||
let ts_sig = match export.generate_typescript {
|
||||
true => Some(ts_sig.as_str()),
|
||||
false => None,
|
||||
};
|
||||
|
||||
let docs = format_doc_comments(&export.comments, Some(js_doc));
|
||||
match &export.kind {
|
||||
AuxExportKind::Function(name) => {
|
||||
self.export(&name, &format!("function{}", code), Some(docs))?;
|
||||
if let Some(ts_sig) = ts_sig {
|
||||
self.typescript.push_str(&docs);
|
||||
self.typescript.push_str("export function ");
|
||||
self.typescript.push_str(&name);
|
||||
self.typescript.push_str(ts_sig);
|
||||
self.typescript.push_str(";\n");
|
||||
}
|
||||
self.export(&name, &format!("function{}", code), Some(&docs))?;
|
||||
self.globals.push_str("\n");
|
||||
self.typescript.push_str("export function ");
|
||||
self.typescript.push_str(&name);
|
||||
self.typescript.push_str(&ts_sig);
|
||||
self.typescript.push_str(";\n");
|
||||
}
|
||||
AuxExportKind::Constructor(class) => {
|
||||
let exported = require_class(&mut self.exported_classes, class);
|
||||
@ -2169,25 +2176,34 @@ impl<'a> Context<'a> {
|
||||
bail!("found duplicate constructor for class `{}`", class);
|
||||
}
|
||||
exported.has_constructor = true;
|
||||
exported.push(&docs, "constructor", "", &code, &ts_sig);
|
||||
exported.push(&docs, "constructor", "", &code, ts_sig);
|
||||
}
|
||||
AuxExportKind::Getter { class, field } => {
|
||||
let ret_ty = ts_ret_ty.unwrap();
|
||||
let ret_ty = match export.generate_typescript {
|
||||
true => match &ts_ret_ty {
|
||||
Some(s) => Some(s.as_str()),
|
||||
_ => None,
|
||||
},
|
||||
false => None,
|
||||
};
|
||||
let exported = require_class(&mut self.exported_classes, class);
|
||||
exported.push_getter(&docs, field, &code, &ret_ty);
|
||||
exported.push_getter(&docs, field, &code, ret_ty);
|
||||
}
|
||||
AuxExportKind::Setter { class, field } => {
|
||||
let arg_ty = ts_arg_tys[0].clone();
|
||||
let arg_ty = match export.generate_typescript {
|
||||
true => Some(ts_arg_tys[0].as_str()),
|
||||
false => None,
|
||||
};
|
||||
let exported = require_class(&mut self.exported_classes, class);
|
||||
exported.push_setter(&docs, field, &code, &arg_ty, might_be_optional_field);
|
||||
exported.push_setter(&docs, field, &code, arg_ty, might_be_optional_field);
|
||||
}
|
||||
AuxExportKind::StaticFunction { class, name } => {
|
||||
let exported = require_class(&mut self.exported_classes, class);
|
||||
exported.push(&docs, name, "static ", &code, &ts_sig);
|
||||
exported.push(&docs, name, "static ", &code, ts_sig);
|
||||
}
|
||||
AuxExportKind::Method { class, name, .. } => {
|
||||
let exported = require_class(&mut self.exported_classes, class);
|
||||
exported.push(&docs, name, "", &code, &ts_sig);
|
||||
exported.push(&docs, name, "", &code, ts_sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2865,19 +2881,27 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
fn generate_enum(&mut self, enum_: &AuxEnum) -> Result<(), Error> {
|
||||
let docs = format_doc_comments(&enum_.comments, None);
|
||||
let mut variants = String::new();
|
||||
|
||||
self.typescript
|
||||
.push_str(&format!("export enum {} {{", enum_.name));
|
||||
if enum_.generate_typescript {
|
||||
self.typescript.push_str(&docs);
|
||||
self.typescript
|
||||
.push_str(&format!("export enum {} {{", enum_.name));
|
||||
}
|
||||
for (name, value) in enum_.variants.iter() {
|
||||
variants.push_str(&format!("{}:{},", name, value));
|
||||
self.typescript.push_str(&format!("\n {},", name));
|
||||
if enum_.generate_typescript {
|
||||
self.typescript.push_str(&format!("\n {},", name));
|
||||
}
|
||||
}
|
||||
if enum_.generate_typescript {
|
||||
self.typescript.push_str("\n}\n");
|
||||
}
|
||||
self.typescript.push_str("\n}\n");
|
||||
self.export(
|
||||
&enum_.name,
|
||||
&format!("Object.freeze({{ {} }})", variants),
|
||||
Some(format_doc_comments(&enum_.comments, None)),
|
||||
Some(&docs),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@ -3163,24 +3187,36 @@ fn require_class<'a>(
|
||||
}
|
||||
|
||||
impl ExportedClass {
|
||||
fn push(&mut self, docs: &str, function_name: &str, function_prefix: &str, js: &str, ts: &str) {
|
||||
fn push(
|
||||
&mut self,
|
||||
docs: &str,
|
||||
function_name: &str,
|
||||
function_prefix: &str,
|
||||
js: &str,
|
||||
ts: Option<&str>,
|
||||
) {
|
||||
self.contents.push_str(docs);
|
||||
self.contents.push_str(function_prefix);
|
||||
self.contents.push_str(function_name);
|
||||
self.contents.push_str(js);
|
||||
self.contents.push_str("\n");
|
||||
self.typescript.push_str(docs);
|
||||
self.typescript.push_str(" ");
|
||||
self.typescript.push_str(function_prefix);
|
||||
self.typescript.push_str(function_name);
|
||||
self.typescript.push_str(ts);
|
||||
self.typescript.push_str(";\n");
|
||||
if let Some(ts) = ts {
|
||||
self.typescript.push_str(docs);
|
||||
self.typescript.push_str(" ");
|
||||
self.typescript.push_str(function_prefix);
|
||||
self.typescript.push_str(function_name);
|
||||
self.typescript.push_str(ts);
|
||||
self.typescript.push_str(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for adding a getter to a class, mainly to ensure that TypeScript
|
||||
/// generation is handled specially.
|
||||
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: &str) {
|
||||
self.push_accessor(docs, field, js, "get ", ret_ty);
|
||||
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: Option<&str>) {
|
||||
self.push_accessor(docs, field, js, "get ");
|
||||
if let Some(ret_ty) = ret_ty {
|
||||
self.push_accessor_ts(field, ret_ty);
|
||||
}
|
||||
self.readable_properties.push(field.to_string());
|
||||
}
|
||||
|
||||
@ -3191,28 +3227,18 @@ impl ExportedClass {
|
||||
docs: &str,
|
||||
field: &str,
|
||||
js: &str,
|
||||
ret_ty: &str,
|
||||
ret_ty: Option<&str>,
|
||||
might_be_optional_field: bool,
|
||||
) {
|
||||
let (has_setter, is_optional) = self.push_accessor(docs, field, js, "set ", ret_ty);
|
||||
*has_setter = true;
|
||||
*is_optional = might_be_optional_field;
|
||||
self.push_accessor(docs, field, js, "set ");
|
||||
if let Some(ret_ty) = ret_ty {
|
||||
let (has_setter, is_optional) = self.push_accessor_ts(field, ret_ty);
|
||||
*has_setter = true;
|
||||
*is_optional = might_be_optional_field;
|
||||
}
|
||||
}
|
||||
|
||||
fn push_accessor(
|
||||
&mut self,
|
||||
docs: &str,
|
||||
field: &str,
|
||||
js: &str,
|
||||
prefix: &str,
|
||||
ret_ty: &str,
|
||||
) -> (&mut bool, &mut bool) {
|
||||
self.contents.push_str(docs);
|
||||
self.contents.push_str(prefix);
|
||||
self.contents.push_str(field);
|
||||
self.contents.push_str(js);
|
||||
self.contents.push_str("\n");
|
||||
|
||||
fn push_accessor_ts(&mut self, field: &str, ret_ty: &str) -> (&mut bool, &mut bool) {
|
||||
let (ty, has_setter, is_optional) = self
|
||||
.typescript_fields
|
||||
.entry(field.to_string())
|
||||
@ -3221,6 +3247,14 @@ impl ExportedClass {
|
||||
*ty = ret_ty.to_string();
|
||||
(has_setter, is_optional)
|
||||
}
|
||||
|
||||
fn push_accessor(&mut self, docs: &str, field: &str, js: &str, prefix: &str) {
|
||||
self.contents.push_str(docs);
|
||||
self.contents.push_str(prefix);
|
||||
self.contents.push_str(field);
|
||||
self.contents.push_str(js);
|
||||
self.contents.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -454,6 +454,7 @@ impl<'a> Context<'a> {
|
||||
comments: concatenate_comments(&export.comments),
|
||||
arg_names: Some(export.function.arg_names),
|
||||
kind,
|
||||
generate_typescript: export.function.generate_typescript,
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
@ -767,6 +768,7 @@ impl<'a> Context<'a> {
|
||||
.iter()
|
||||
.map(|v| (v.name.to_string(), v.value))
|
||||
.collect(),
|
||||
generate_typescript: enum_.generate_typescript,
|
||||
};
|
||||
self.aux.enums.push(aux);
|
||||
Ok(())
|
||||
@ -799,6 +801,7 @@ impl<'a> Context<'a> {
|
||||
class: struct_.name.to_string(),
|
||||
field: field.name.to_string(),
|
||||
},
|
||||
generate_typescript: field.generate_typescript,
|
||||
},
|
||||
);
|
||||
|
||||
@ -824,6 +827,7 @@ impl<'a> Context<'a> {
|
||||
class: struct_.name.to_string(),
|
||||
field: field.name.to_string(),
|
||||
},
|
||||
generate_typescript: field.generate_typescript,
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -831,6 +835,7 @@ impl<'a> Context<'a> {
|
||||
name: struct_.name.to_string(),
|
||||
comments: concatenate_comments(&struct_.comments),
|
||||
is_inspectable: struct_.is_inspectable,
|
||||
generate_typescript: struct_.generate_typescript,
|
||||
};
|
||||
self.aux.structs.push(aux);
|
||||
|
||||
@ -1048,6 +1053,7 @@ impl<'a> Context<'a> {
|
||||
comments: String::new(),
|
||||
arg_names: None,
|
||||
kind,
|
||||
generate_typescript: true,
|
||||
};
|
||||
assert!(self.aux.export_map.insert(id, export).is_none());
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ pub struct AuxExport {
|
||||
pub arg_names: Option<Vec<String>>,
|
||||
/// What kind of function this is and where it shows up
|
||||
pub kind: AuxExportKind,
|
||||
/// Whether typescript bindings should be generated for this export.
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
/// All possible kinds of exports from a wasm module.
|
||||
@ -131,7 +133,10 @@ pub struct AuxEnum {
|
||||
/// The copied Rust comments to forward to JS
|
||||
pub comments: String,
|
||||
/// A list of variants with their name and value
|
||||
/// and whether typescript bindings should be generated for each variant
|
||||
pub variants: Vec<(String, u32)>,
|
||||
/// Whether typescript bindings should be generated for this enum.
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -142,6 +147,8 @@ pub struct AuxStruct {
|
||||
pub comments: String,
|
||||
/// Whether to generate helper methods for inspecting the class
|
||||
pub is_inspectable: bool,
|
||||
/// Whether typescript bindings should be generated for this struct.
|
||||
pub generate_typescript: bool,
|
||||
}
|
||||
|
||||
/// All possible types of imports that can be imported by a wasm module.
|
||||
|
@ -51,6 +51,7 @@ macro_rules! attrgen {
|
||||
(vendor_prefix, VendorPrefix(Span, Ident)),
|
||||
(variadic, Variadic(Span)),
|
||||
(typescript_custom_section, TypescriptCustomSection(Span)),
|
||||
(skip_typescript, SkipTypescript(Span)),
|
||||
(start, Start(Span)),
|
||||
(skip, Skip(Span)),
|
||||
(typescript_type, TypeScriptType(Span, String, Span)),
|
||||
@ -354,9 +355,11 @@ impl<'a> ConvertToAst<BindgenAttrs> for &'a mut syn::ItemStruct {
|
||||
getter: Ident::new(&getter, Span::call_site()),
|
||||
setter: Ident::new(&setter, Span::call_site()),
|
||||
comments,
|
||||
generate_typescript: attrs.skip_typescript().is_none(),
|
||||
});
|
||||
attrs.check_used()?;
|
||||
}
|
||||
let generate_typescript = attrs.skip_typescript().is_none();
|
||||
let comments: Vec<String> = extract_doc_comments(&self.attrs);
|
||||
attrs.check_used()?;
|
||||
Ok(ast::Struct {
|
||||
@ -365,6 +368,7 @@ impl<'a> ConvertToAst<BindgenAttrs> for &'a mut syn::ItemStruct {
|
||||
fields,
|
||||
comments,
|
||||
is_inspectable,
|
||||
generate_typescript,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -720,6 +724,7 @@ fn function_from_decl(
|
||||
rust_attrs: attrs,
|
||||
rust_vis: vis,
|
||||
r#async: sig.asyncness.is_some(),
|
||||
generate_typescript: opts.skip_typescript().is_none(),
|
||||
},
|
||||
method_self,
|
||||
))
|
||||
@ -798,11 +803,12 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
|
||||
};
|
||||
f.macro_parse(program, opts)?;
|
||||
}
|
||||
syn::Item::Enum(e) => {
|
||||
if let Some(opts) = opts {
|
||||
opts.check_used()?;
|
||||
}
|
||||
e.macro_parse(program, (tokens,))?;
|
||||
syn::Item::Enum(mut e) => {
|
||||
let opts = match opts {
|
||||
Some(opts) => opts,
|
||||
None => BindgenAttrs::find(&mut e.attrs)?,
|
||||
};
|
||||
e.macro_parse(program, (tokens, opts))?;
|
||||
}
|
||||
syn::Item::Const(mut c) => {
|
||||
let opts = match opts {
|
||||
@ -1032,15 +1038,17 @@ fn import_enum(enum_: syn::ItemEnum, program: &mut ast::Program) -> Result<(), D
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<'a> MacroParse<(&'a mut TokenStream,)> for syn::ItemEnum {
|
||||
impl<'a> MacroParse<(&'a mut TokenStream, BindgenAttrs)> for syn::ItemEnum {
|
||||
fn macro_parse(
|
||||
self,
|
||||
program: &mut ast::Program,
|
||||
(tokens,): (&'a mut TokenStream,),
|
||||
(tokens, opts): (&'a mut TokenStream, BindgenAttrs),
|
||||
) -> Result<(), Diagnostic> {
|
||||
if self.variants.len() == 0 {
|
||||
bail_span!(self, "cannot export empty enums to JS");
|
||||
}
|
||||
let generate_typescript = opts.skip_typescript().is_none();
|
||||
opts.check_used()?;
|
||||
|
||||
// Check if the first value is a string literal
|
||||
match self.variants[0].discriminant {
|
||||
@ -1141,8 +1149,8 @@ impl<'a> MacroParse<(&'a mut TokenStream,)> for syn::ItemEnum {
|
||||
variants,
|
||||
comments,
|
||||
hole,
|
||||
generate_typescript,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ macro_rules! shared_api {
|
||||
name: &'a str,
|
||||
variants: Vec<EnumVariant<'a>>,
|
||||
comments: Vec<&'a str>,
|
||||
generate_typescript: bool,
|
||||
}
|
||||
|
||||
struct EnumVariant<'a> {
|
||||
@ -110,6 +111,7 @@ macro_rules! shared_api {
|
||||
struct Function<'a> {
|
||||
arg_names: Vec<String>,
|
||||
name: &'a str,
|
||||
generate_typescript: bool,
|
||||
}
|
||||
|
||||
struct Struct<'a> {
|
||||
@ -117,12 +119,14 @@ macro_rules! shared_api {
|
||||
fields: Vec<StructField<'a>>,
|
||||
comments: Vec<&'a str>,
|
||||
is_inspectable: bool,
|
||||
generate_typescript: bool,
|
||||
}
|
||||
|
||||
struct StructField<'a> {
|
||||
name: &'a str,
|
||||
readonly: bool,
|
||||
comments: Vec<&'a str>,
|
||||
generate_typescript: bool,
|
||||
}
|
||||
|
||||
struct LocalModule<'a> {
|
||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
wasm-bindgen = { path = '../..' }
|
||||
web-sys = { path = '../web-sys', features = [ 'HtmlElement', 'Node', 'Document' ] }
|
||||
js-sys = { path = '../js-sys' }
|
||||
|
||||
[lib]
|
||||
crate-type = ['cdylib']
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod custom_section;
|
||||
pub mod getters_setters;
|
||||
pub mod omit_definition;
|
||||
pub mod opt_args_and_ret;
|
||||
pub mod optional_fields;
|
||||
pub mod simple_fn;
|
||||
|
34
crates/typescript-tests/src/omit_definition.rs
Normal file
34
crates/typescript-tests/src/omit_definition.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(typescript_custom_section)]
|
||||
const TYPE_GET_VALUE: &'static str =
|
||||
"export function take_function(func: (x: number) => void): void;";
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn take_function(_: js_sys::Function) {}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct MyExportedStruct {
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub field: bool,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl MyExportedStruct {
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn method(&mut self) {
|
||||
self.field = !self.field;
|
||||
}
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn static_func() {
|
||||
panic!("oh no!");
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub enum MyEnum {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
}
|
26
crates/typescript-tests/src/omit_definition.ts
Normal file
26
crates/typescript-tests/src/omit_definition.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import * as wbg from '../pkg/typescript_tests';
|
||||
|
||||
wbg.take_function((value) => {
|
||||
// `value` should be inferred as `number` because of the
|
||||
// custom typescript section. If `typescript = false` does
|
||||
// not prevent the generation of a signature that takes any
|
||||
// function, then this will trigger a noImplicitAny error.
|
||||
console.log(value);
|
||||
});
|
||||
|
||||
declare function assert<T>(message: T): void;
|
||||
|
||||
type EnableIfEnum = "MyEnum" extends keyof typeof wbg ? never : string;
|
||||
assert<EnableIfEnum>("`MyEnum` type should not be exported.");
|
||||
|
||||
type EnableIfStruct = "MyStruct" extends keyof typeof wbg ? never : string;
|
||||
assert<EnableIfStruct>("`MyStruct` type should not be exported.");
|
||||
|
||||
type EnableIfField = "field" extends keyof wbg.MyExportedStruct ? never : string;
|
||||
assert<EnableIfField>("`field` should not exist on `MyExportedStruct`.");
|
||||
|
||||
type EnableIfMethod = "method" extends keyof wbg.MyExportedStruct ? never : string;
|
||||
assert<EnableIfMethod>("`method` should not exist on `MyExportedStruct`.");
|
||||
|
||||
type EnableIfStaticMethod = "static_func" extends keyof typeof wbg.MyExportedStruct ? never : string;
|
||||
assert<EnableIfStaticMethod>("`static_func` should not exist on `MyExportedStruct`.");
|
@ -0,0 +1,42 @@
|
||||
# `skip_typescript`
|
||||
|
||||
By default, Rust exports exposed to JavaScript will generate TypeScript definitions (unless `--no-typescript` is used). The `skip_typescript` attribute can be used to disable type generation per function, enum, struct, or field. For example:
|
||||
|
||||
```rust
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub enum MyHiddenEnum {
|
||||
One,
|
||||
Two,
|
||||
Three
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct MyPoint {
|
||||
pub x: u32,
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl MyPoint {
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn stringify(&self) -> String {
|
||||
format!("({}, {})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Will generate the following `.d.ts` file:
|
||||
|
||||
```ts
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export class MyPoint {
|
||||
free(): void;
|
||||
x: number;
|
||||
}
|
||||
```
|
||||
|
||||
When combined with [the `typescript_custom_section` attribute](typescript_custom_section.html), this can be used to manually specify more specific function types instead of using the generated definitions.
|
Loading…
x
Reference in New Issue
Block a user