diff --git a/CHANGELOG.md b/CHANGELOG.md index 6200484..4170b6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `branch()` is now allowed to be used within a reactive scope. +### Deprecated + +- `create()` overloads. Supported is now only `create(class)(props)`. + -------------------------------------------------------------------------------- ## [0.4.0] - 2026-01-17 diff --git a/src/create.luau b/src/create.luau index 3540555..db33663 100644 --- a/src/create.luau +++ b/src/create.luau @@ -5,11 +5,10 @@ local defaults = require "./defaults" local apply = require "./apply" local flags = require "./flags" -local ctor_cache = {} :: { [string]: (AnyProps) -> Instance } -local function lazy_init(_, class: string) - local function ctor(properties: AnyProps): Instance +local function create_constructor_for_class(class: string): ({ [unknown]: unknown }) -> Instance + local function constructor(properties: { [unknown]: unknown }): Instance local ok, instance: Instance = pcall(Instance.new, class :: any) - if not ok then error(`invalid class name { class }`, 0) end + if not ok then error(`invalid class name {class}`, 0) end if flags.defaults then local default: { [string]: unknown }? = defaults[class] @@ -23,28 +22,34 @@ local function lazy_init(_, class: string) return apply(instance, properties) end - ctor_cache[class] = ctor - return ctor + return constructor end -setmetatable(ctor_cache, { __index = lazy_init }) + +local constructor_cache = {} :: { [string]: ({ [unknown]: unknown }) -> Instance } -- todo: remove support for different overloads -local function create(class_or_instance: string|Instance, properties: AnyProps?): ((AnyProps) -> Instance) | Instance +local function create(class_or_instance: string|Instance, properties: { [unknown]: unknown }?): unknown if type(class_or_instance) ~= "string" and typeof(class_or_instance) ~= "Instance" then error("bad argument #1, expected string or instance, got " .. typeof(class_or_instance), 0) end - local ctor = if type(class_or_instance) == "string" - then ctor_cache[class_or_instance] - else function(properties) - local clone = class_or_instance:Clone() - if not clone then error "attempt to clone a non-archivable instance" end - return apply(clone, properties) + local constructor: ({ [unknown]: unknown }) -> Instance + if type(class_or_instance) == "string" then + constructor = constructor_cache[class_or_instance] + if not constructor then + constructor = create_constructor_for_class(class_or_instance) + constructor_cache[class_or_instance] = constructor end + else + constructor = function(props) + local clone = assert(class_or_instance:Clone(), "attempt to clone a non-archivable instance") + return apply(clone, props) + end + end return if properties - then ctor(properties) - else ctor + then constructor(properties) + else constructor end type Instances = { @@ -97,13 +102,6 @@ type function Properties(instance: type?) return properties end -type AnyProps = { [any]: any } -type Create = ( - (Instance) -> (AnyProps) -> Instance -) & ( - (string, AnyProps) -> Instance -) & ( - (Name|keyof) -> (Properties>) -> index -) +type Create = (Name|keyof|"") -> (Properties>) -> index -return (create :: any) :: Create +return create :: Create diff --git a/src/defaults.luau b/src/defaults.luau index bcdabaf..77040ff 100644 --- a/src/defaults.luau +++ b/src/defaults.luau @@ -110,4 +110,4 @@ return { BorderColor3 = Color3.new(0, 0, 0), BorderSizePixel = 0 } -} +} :: { [string]: { [string]: unknown} } diff --git a/test/create-types.luau b/test/create-types.luau index 3a1e6fd..b30ffd5 100644 --- a/test/create-types.luau +++ b/test/create-types.luau @@ -1,52 +1,8 @@ -type Pseudo = { - Test: number -} - -type Instances = { - TextLabel: TextLabel, - TextButton: TextButton, - ImageLabel: ImageLabel, - Pseudo: Pseudo -} - -type function Properties(instance: type?) - local properties = types.newtable() - - while instance do - for i, v in instance:properties() do - local connector = v.read and v.read.tag == "table" and v.read:readproperty(types.singleton("Connect")) - if connector then - if not connector then continue end - local params = connector:parameters().head - if not params then continue end - local listener = params[2] - if not listener then continue end - properties:setproperty(i, types.optional(listener)) - elseif v.write then - properties:setproperty(i, types.optional(types.unionof( - v.write, - types.newfunction({}, { head = { v.write } }) - ))) - end - end - - instance = instance:readparent() - end - - properties:setindexer(types.number, types.any) - - return properties -end - -local function create(name: Name | keyof): (Properties>) -> index - return function() - return "" :: any - end -end - local vide = require "../src/" + local count = vide.source(0) -create("TextButton") { -- todo: why is `:: "TextButton"` not necessary? + +vide.create("TextButton") { BackgroundTransparency = 1, AnchorPoint = "bad value", -- should error InvalidProperty = true, -- should error @@ -65,6 +21,7 @@ create("TextButton") { -- todo: why is `:: "TextButton"` not necessary? Activated = "bad value", -- should error - create "TextLabel" {}, + vide.create "TextLabel" {}, + function() end, }