esx-framework / esx_core

Official Repo For core resources for esx-legacy
https://documentation.esx-framework.org/
GNU General Public License v3.0
368 stars 733 forks source link

feat: add TypeCheck to check value types #1309

Closed CENSOR1337 closed 5 months ago

CENSOR1337 commented 8 months ago

Add a utility function that allow to check value types

as I say in source code Need feedback on this one, should we assert or return false and error message? I prefer assert, but I'm open to suggestions

Thank you.

Here an examples

Example: 1

local value = 1
ESX.TypeCheck(value, "number") -- true

Example: 2

local value = "hello"
ESX.TypeCheck(value, "number", "string") -- true

Example: 3

local value = "hello"
ESX.TypeCheck(value, "number") -- false, "bad value (number expected, got string)"

Example: 4

local value = "hello"
ESX.TypeCheck(value, "boolean", "number", "table") -- false, "bad value (boolean or number or table expected, got string)"

Example: 5

local value = nil
ESX.TypeCheck(value, "boolean", "number", "table") -- false, "bad value (boolean or number or table expected, got nil)"

Example: 6

local value = nil
ESX.TypeCheck(value, "boolean", "number", "table", "nil") -- true
CENSOR1337 commented 8 months ago

With this function we will able to improve readability of code Example setMeta function from

function self.setMeta(index, value, subValue)
    if not index then
        return print("[^1ERROR^7] xPlayer.setMeta ^5index^7 is Missing!")
    end

    if type(index) ~= "string" then
        return print("[^1ERROR^7] xPlayer.setMeta ^5index^7 should be ^5string^7!")
    end

    if value == nil then
        return print("[^1ERROR^7] xPlayer.setMeta value is missing!")
    end

    local _type = type(value)

    if not subValue then
        if _type ~= "number" and _type ~= "string" and _type ~= "table" then
            return print(("[^1ERROR^7] xPlayer.setMeta ^5%s^7 should be ^5number^7 or ^5string^7 or ^5table^7!"):format(value))
        end

        self.metadata[index] = value
    else
        if _type ~= "string" then
            return print(("[^1ERROR^7] xPlayer.setMeta ^5value^7 should be ^5string^7 as a subIndex!"):format(value))
        end

        if not self.metadata[index] or type(self.metadata[index]) ~= "table" then
            self.metadata[index] = {}
        end

        self.metadata[index] = type(self.metadata[index]) == "table" and self.metadata[index] or {}
        self.metadata[index][value] = subValue
    end

    Player(self.source).state:set("metadata", self.metadata, true)
end

to

function self.setMeta(index, value, subValue)
    ESX.TypeCheck(index, "string")

    if not subValue then
        ESX.TypeCheck(value, "number", "string", "table")

        self.metadata[index] = value
    else
        ESX.TypeCheck(value, "string")

        ESX.TypeCheck(subValue, "number", "string", "table")

        if not self.metadata[index] or type(self.metadata[index]) ~= "table" then
            self.metadata[index] = {}
        end

        self.metadata[index] = type(self.metadata[index]) == "table" and self.metadata[index] or {}
        self.metadata[index][value] = subValue
    end

    Player(self.source).state:set("metadata", self.metadata, true)
end
CENSOR1337 commented 7 months ago

Due to last commit, I decided to removed TypeCheck and add AssertType and ValidateType instead

 - replaced `TypeCheck` with `AssertType` this function will assert
 - add : `ValidateType` this function will return Boolean and error message

Here is an update code

function self.setMeta(index, value, subValue)
    ESX.AssertType(index, "string")

    if not subValue then
        ESX.AssertType(value, "number", "string", "table")

        self.metadata[index] = value
    else
        ESX.AssertType(value, "string")

        ESX.AssertType(subValue, "number", "string", "table")

        if not self.metadata[index] or type(self.metadata[index]) ~= "table" then
            self.metadata[index] = {}
        end

        self.metadata[index] = type(self.metadata[index]) == "table" and self.metadata[index] or {}
        self.metadata[index][value] = subValue
    end

    Player(self.source).state:set("metadata", self.metadata, true)
end

Example of ValidateType

local value = 1

if (ESX.ValidateType(value, "number")) then
    print("value is a number")
else
    print("value is not a number")
end
Gellipapa commented 7 months ago

Hi! @CENSOR1337 I like this kind of solution, but it would be nice if we could also support ENUM types. I'm thinking here I'll give a table string and if it matches one of those then it's the right type but thanks for pr.

How do you check the boolean types, if I type 1 is it now number or boolean?

It would be nice to have a way to determine from a string "true" or 1 whether it is a boolean value.

The latter might not be used, it's just an idea.

What do you think about this?

CENSOR1337 commented 7 months ago

Hi! @CENSOR1337 I like this kind of solution, but it would be nice if we could also support ENUM types. I'm thinking here I'll give a table string and if it matches one of those then it's the right type but thanks for pr.

How do you check the boolean types, if I type 1 is it now number or boolean?

It would be nice to have a way to determine from a string "true" or 1 whether it is a boolean value.

The latter might not be used, it's just an idea.

What do you think about this?

Hey, that's great to hear! I think if we want to add support for other data types with specific conditions, it might be better to create separate functions for. This keeps the current function focused on providing type safety for the core Lua data types: boolean, function, nil, number, string, and table.

Regarding your question about checking for boolean types specifically: How do you check the boolean types, if I type 1 is it now number or boolean? using this function I believed using this example would be a great choice

local a_simple_value = 1
if (ESX.ValidateType(a_simple_value, "number", "boolean")) then
    print("a_simple_value is a number or a boolean")
else
    print("a_simple_value is not a number or a boolean")
end
Gellipapa commented 7 months ago

Hi! @CENSOR1337 I like this kind of solution, but it would be nice if we could also support ENUM types. I'm thinking here I'll give a table string and if it matches one of those then it's the right type but thanks for pr. How do you check the boolean types, if I type 1 is it now number or boolean? It would be nice to have a way to determine from a string "true" or 1 whether it is a boolean value. The latter might not be used, it's just an idea. What do you think about this?

Hey, that's great to hear! I think if we want to add support for other data types with specific conditions, it might be better to create separate functions for. This keeps the current function focused on providing type safety for the core Lua data types: boolean, function, nil, number, string, and table.

Regarding your question about checking for boolean types specifically: How do you check the boolean types, if I type 1 is it now number or boolean? using this function I believed using this example would be a great choice

local a_simple_value = 1
if (ESX.ValidateType(a_simple_value, "number", "boolean")) then
    print("a_simple_value is a number or a boolean")
else
    print("a_simple_value is not a number or a boolean")
end

Hi! Yes,it's legitimate not to complicate it in the first place, it's also a big enough help to write more readable code. Thanks your pr.

CENSOR1337 commented 7 months ago

Please remove brackets in code, lua don't needed and i can merge. Thanks.

I have removed some of brackets, Let me know what you think. Thanks.

Gellipapa commented 5 months ago

@CENSOR1337 Hi! Thanks i merged.

CENSOR1337 commented 5 months ago

@CENSOR1337 Hi! Thanks i merged.

Thank you.